这段时间对 Node 爬虫进行了一些学习和实战,可以自己爬取一些页面了,这里简单总结一下。

爬虫介绍

通过模拟浏览器的请求,服务器就会根据我们的请求返回我们想要的数据,将数据解析出来,并且进行保存。

爬虫流程

目标:确定你想要获取的数据

  1. 确定想要的数据在什么页面上(一般详细的数据会在详情页)
  2. 确定在哪些页面可以链接到这些页面(一般分类列表页面会有详情页的链接数据)
  3. 寻找页面之间和数据之间的规律

分析页面

  1. 获取数据的方式(正则,cherrio)
  2. 分析数据是通过 ajax 请求的数据,还是 html 里自带的数据
  3. 如果是通过 AJAX 请求的数据,那么需要获取 ajax 请求的链接,一般请求到的数据都为 JSON 格式数据,那么就会比较容易解析。
  4. 如何数据在 HTML 里面,那么就用 cherrio 通过选择器将内容选中

编写单个数据获取的案例

  1. 解析出分类页的链接地址
  2. 解析出列表页的链接地址
  3. 解析出详情页的链接地址
  4. 解析详情页里面想要获取的数据
  5. 将数据进行保存到本地或者是数据库

如果遇到阻碍进行反爬虫对抗

  1. User-Agent 是否是正常浏览器的信息
  2. 将请求头设置成跟浏览器一样的内容
  3. 因为爬虫的爬取速度过快,会导致封号。1 那么可以降低速度进行解决,2 可以使用代理进行解决
  4. 如果设置需要凭证,那么可以采用无界浏览器真实模拟。

请求数据的库

request,axios:通过库,帮助我们快速实现 HTTP 请求包的打包

1
2
3
4
5
6
7
8
9
request.get(
'请求地址',
{
请求头字段: '请求头的value值',
},
(res) => {
处理返回的内容
}
)

axios 优势会更明显,前后端通杀,前后端调用的方式一致。

1
2
3
axios.get('请求地址', 参数对象).then(function (response) {
console.log(response)
})

axios 获取图片

1
2
3
4
5
6
7
axios({
method: 'get',
url: 'http://bit.ly/2mTM3nY',
responseType: 'stream',
}).then(function (response) {
response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
})

puppeteer:完全模拟浏览器

打开浏览器

1
2
3
4
5
6
7
8
9
10
let options = {
headless:true,//是否是无界面浏览器
slowMo:250,//调试时可以减慢操作速度
defaultViewport:{
width:1200,//设置视窗的宽高
height:800
},
timeout:3000//默认超时3秒
}
let browser =await puppeteer.launch(options);

打开新标签页

1
let page = await browser.newPage()

获取所有浏览器中的页面

1
let pages = await browser.pages()

关闭浏览器

1
browser.close()

将页面跳转至

1
await page.goto(url)

获取页面的对象,并进行操作

1
2
3
4
5
6
let btn = await page.$(selector)
let input = await page.$(selector)
//点击按钮
btn.click()
//聚焦到输入框
input.forcus()

在页面上写入内容或者键盘按键

1
2
3
await page.keyboard.type('Hello World!')
await page.keyboard.press('ArrowLeft')
await page.keyboard.down('Shift')

设置鼠标的移动

1
2
3
4
5
6
7
await page.mouse.move(0, 0)
await page.mouse.down()
await page.mouse.move(0, 100)
await page.mouse.move(100, 100)
await page.mouse.move(100, 0)
await page.mouse.move(0, 0)
await page.mouse.up()

截获页面请求

1
2
3
4
5
6
7
8
9
await page.setRequestInterception(true)
page.on('request', (request) => {
request.url() //可以获取请求的网址,request,包含了所有的请求信息
if (你想要的条件) {
request.continue()
} else {
request.abort([errorCode])
}
})

获取浏览器的信息和内容

1
2
3
4
5
6
page.$eval(selector, (item) => {
return item
})
page.$$eval(selectors, (items) => {
return items
})