爬虫与NodeJs(一)
特别申明:阅读本文之后,请勿滥用爬虫采集资源,攻击他人服务器。
网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
开门见山,小编所接触到的爬虫分为两种,一种为基本的http或https请求,使用网络请求来获取目标内容。第二种为无头浏览器,可以将目标页面直接运行在无头浏览器中。两种方法各有利弊,接下来我们详细了解一下。
小编是一名前端程序员,熟悉javascript,所以这里的举例都是使用nodejs代码。先来说说第一种爬虫,使用http请求的方式。
http请求
我们可以使用nodejs种的http(s)模块来请求目标网址,也可以使用axios
这样的第三方库来请求网页。拿到html后使用html解析库将其解析为方便操作的js对象,然后抓去目标内容。解析库这里推荐使用cheerio
。cheerio提供了类似jQuery的操作方法,可以轻松的抓去到我们想要的内容。
// demo1
const cheerio = require('cheerio')
const axios = require('axios')
async function main() {
const resp = await axios.get('https://www.jianshu.com/')
console.log(resp.data)
}
main()
通过node demo1
执行demo1,我们可以拿到简书首页的html。
我们现在来完善demo1的代码,将html使用cheerio解析。
// demo1
const cheerio = require('cheerio')
const axios = require('axios')
async function main() {
const resp = await axios.get('https://www.jianshu.com/')
const $ = cheerio.load(resp.data)
const articleList = []
$('#list-container li').each((i, el) => {
articleList.push({
id: $(el).attr('id').replace('note-', ''),
title: unescape($(el).find('.title').html().replace(/&#x/g, '%u').replace(/;/g, '')),
href: $(el).find('.title').attr('href'),
})
})
console.log(articleList)
}
main()
image.png
这样我们就拿到了文章的id,标题和链接了。
这种方式抓取数据的优点是效率高,占用的硬件资源也很少。但是这种方法也存在一些劣势。例如懒加载页面就很难爬取。因为懒加载的页面的内容是由浏览器js动态加载的,这样一来,我们所请求到的页面,由于js还没有将内容渲染到页面上,我们就无法正确拿到页面内容,并且我们的请求也无法提供页面js所需的运行环境。这时候就要引出我们的另一种爬虫了。
无头浏览器
无头浏览器是指没有操作界面的,在后台运行的网络浏览器程序。常用的无头浏览器有PhantomJS,Selenium,Puppeteer等(还有很多很多哦,有兴趣可以自己查阅)。
无头浏览器常被用于自动化测试、爬虫等技术。它提供了浏览器js所需的运行环境,我们可以利用这一点,来对付懒加载的页面。
Puppeteer是谷歌发布的一款Chromium无头浏览器。在这里我们以Puppeteer为例,来写一些小demo。
// demo2
const puppeteer = require('puppeteer');
async function main() {
const browser = await puppeteer.launch({
// 是否为无头,无头模式下没有用户操作界面
headless: false,
defaultViewport: null
})
const page = await browser.newPage();
await page.goto('https://www.jianshu.com/u/04d11dd2f924');
}
main()
我们来使用node demo2
来执行:
我们现在已经使用代码打开了一个浏览器窗口。接下来,我们将继续完善demo2来抓取此页面的内容。
// demo2
const puppeteer = require('puppeteer');
async function main() {
const browser = await puppeteer.launch({
// 是否为无头,无头模式下没有用户操作界面
headless: false,
defaultViewport: null,
devtools: true,
})
const page = await browser.newPage();
await page.goto('https://www.jianshu.com/u/04d11dd2f924');
const articleList = await page.$$eval('#list-container li', els =>
els.map(el => {
const id = el.dataset.noteId
const title = el.querySelector('.title').innerText
const url = el.querySelector('.title').href
return {id, title, url}
})
)
console.log(articleList)
}
main()
执行该代码,我们得到如下结果:
image.png
这就是无头浏览器的基本使用。它还提供了很多方便操作的API,例如page.waitFor(selector, pageFun)
方法,可以等待某个元素出现在页面后再去执行pageFun方法.还有page.addScriptTag(options)
方法,可以直接在页面注入你自己的js脚本。
在这里,再次申明,请勿滥用爬虫采集资源,攻击他人服务器。
两种方式的对比
http 方式:
优点:占用的硬件资源少,响应速度更快;
缺点:无法抓取懒加载页面,无法获取更多信息,例如cookie,localStorage等。
无头浏览器 方式:
优点:提供完整浏览器运行环境,可以抓取懒加载页面的内容,也可以获取页面cookie等本地存储,可以在页面注入js代码,可以模拟键盘输入,鼠标点击等操作;
缺点:占用的硬件资源高,会去执行页面代码,在关闭无头模式的情况下还要去渲染页面,响应速度慢。
详细对比了两种方式以后,我们发现两种方式各有利弊。其实,在实际使用中,我们可以混搭使用,既保证了执行效率,同样也能保证信息的完整性。
今天就介绍道这里了,喜欢的简友可以点赞并关注,随后我就继续更新几篇爬虫相关的文章。
本文版权所有,禁止转载!