程序员从入门到放弃

爬虫与NodeJs(一)

2019-10-20  本文已影响0人  曦惜夕

特别申明:阅读本文之后,请勿滥用爬虫采集资源,攻击他人服务器。

网络爬虫(又称为网页蜘蛛,网络机器人,在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。

image.png

我们现在来完善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来执行:

image.png

我们现在已经使用代码打开了一个浏览器窗口。接下来,我们将继续完善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代码,可以模拟键盘输入,鼠标点击等操作;
缺点:占用的硬件资源高,会去执行页面代码,在关闭无头模式的情况下还要去渲染页面,响应速度慢。

详细对比了两种方式以后,我们发现两种方式各有利弊。其实,在实际使用中,我们可以混搭使用,既保证了执行效率,同样也能保证信息的完整性。

今天就介绍道这里了,喜欢的简友可以点赞并关注,随后我就继续更新几篇爬虫相关的文章。

本文版权所有,禁止转载!

上一篇下一篇

猜你喜欢

热点阅读