【每周小项目】使用 puppeteer 插件爬取动态网站
0. 前言
这两天对爬虫开始感兴趣,最开始是源于天涯的一个房价神贴,盖了上万层,追着读了好久。天涯网页端的“只看楼主”需要会员,手机端可以“只看楼主”,但是体验不太好,记录也不方便,于是决定把楼主发言单独爬下来,既可以保存,也可以检索。
最开始想法很简单,对每一页进行元素检索,发帖人与楼主名字匹配的,就把里面的content拷出来。
首先在网上找到的工具是cheerio插件,它在读取网站之后,将网站内容存下来,通过元素选择器进行内容选取。在使用递归后,还能解决翻页问题。
事实上也确实如此,通过简单几步操作,就把楼主的发言保存了下来,也让我对爬虫产生了兴趣。
问题
cheerio确实简单好用,在应对简单静态网页时没有问题。但对付具备一定反爬机制的网站就无能为力了。比如cheerio解决翻页问题,靠的是动态修改url链接。但是有的网站,比如我最爱的煎蛋,它的网页链接页码是乱码,就没办法实现自动翻页。再比如有的房产网站,在罗列在售资源时,为了用户体验,使用了懒加载,只有将页面滚动到底部后,才能触发加载。
以上种种实际上就是cheerio对于网页操作是无能为力的。
解决
在网上查找对付懒加载的方法时,发现了puppeteer插件。谷歌浏览器在17年自行开发了Chrome Headless特性,并与之同时推出了puppeteer,本质上就是一个不含界面的浏览器,有点像电脑的终端,所有操作都通过代码进行操作。
这样,我们就可以在对网站进行检索之前,操作指定元素滚动到底部,以触发更多信息。或者在需要翻页的时候,操作代码对翻页按钮进行点击,然后对翻页后的页面进行相关处理。
1. 下载与引包
// 下载
npm i puppeteer
// 引包
const puppeteer = require('puppeteer')
2. 使用步骤
// 将整个操作放置在一个闭包的异步函数中,以便于进行异步操作
(async () => {
// 1. 使用puppetee插件启动一个浏览器,并开启一个新页面
const brower = await puppeteer.launch({
args: ['--no-sandbox'],
dumpio: false,
headless:false, // 默认为true,设为false时,可以显示可视化浏览器界面
})
const page = await brower.newPage() // 开启一个新页面
// 2. 打开指定网页
await page.goto('http://jandan.net/ooxx', {
waitUntil: 'networkidle2' // 网络空闲说明已加载完毕
});
// 3. 对动态网站进行自动化操作,这一步是其精髓所在
// 由于我们监控的是动态网页,刚打开网页时,所需元素也许还未出现,所以需要进行监听,例如“下一页按钮”
await page.waitForSelector('a.previous-comment-page'); // 括号内是元素选择器
// 当下一页按钮出现时,模拟点击
await page.click('a.previous-comment-page')
// 4. 这时我们可以执行爬取我们需要的数据了,我们可以去审查页面的dom结果,来循环遍历这些数据。
// page.evaluate() 为在浏览器中执行函数,相当于在控制台中执行函数,返回一个 Promise
const result = await page.evaluate(() => {
// 拿到页面上的jQuery
var $ = window.$;
// 在这里进行熟悉的 DOM 操作
// Do something
});
// 5. 关闭浏览器,在console里面打印我们需要的数据
brower.close();
// 6. 对结果进行处理
console.log(result);
})();
3. 爬过的几个坑
page.evaluate 的传参问题
因为打开的这个 page 只是一个木偶,并不是真正的浏览器页面,所以在这个页面上的操作与一般页面上的操作有差异。

官方文档里说,这个参数是这样的。在实际使用中,可以传一个字符串变量,但是到更复杂一点的,比如‘fs’,自定义外部函数时,都无法读取。
这也是我建议在第6步,对页面操作完成后,统一对结果进行处理。(主要是因为我没有解决这个问题,所以认怂绕开走了……)
元素操作问题
puppeteer中,最重要的函数执行和要素选择都与一般浏览器上操作有些区别,这里有些坑要爬,现在我也说不清楚。
【每周小项目】使用 puppeteer 插件爬取动态网站的更多相关文章
- python3爬取动态网站图片
思路: 1.图片放在<image>XXX</image>标签中 2.利用fiddler抓包获取存放图片信息的js文件url 3.利用requests库获取html内容,然后获取 ...
- Python 爬虫练习项目——异步加载爬取
项目代码 from bs4 import BeautifulSoup import requests url_prefix = 'https://knewone.com/discover?page=' ...
- 用Python爬取斗鱼网站的一个小案例
思路解析: 1.我们需要明确爬取数据的目的:为了按热度查看主播的在线观看人数 2.浏览网页源代码,查看我们需要的数据的定位标签 3.在代码中发送一个http请求,获取到网页返回的html(需要注意的是 ...
- webmagic爬取渲染网站
最近突然得知之后的工作有很多数据采集的任务,有朋友推荐webmagic这个项目,就上手玩了下.发现这个爬虫项目还是挺好用,爬取静态网站几乎不用自己写什么代码(当然是小型爬虫了~~|). 好了,废话少说 ...
- 爬虫系列4:Requests+Xpath 爬取动态数据
爬虫系列4:Requests+Xpath 爬取动态数据 [抓取]:参考前文 爬虫系列1:https://www.cnblogs.com/yizhiamumu/p/9451093.html [分页]:参 ...
- Golang+chromedp+goquery 简单爬取动态数据
目录 Golang+chromedp+goquery 简单爬取动态数据 Golang的安装 下载golang软件 解压golang 配置golang 重新导入配置 chromedp框架的使用 实际的代 ...
- 爬虫系列2:Requests+Xpath 爬取租房网站信息
Requests+Xpath 爬取租房网站信息 [抓取]:参考前文 爬虫系列1:https://www.cnblogs.com/yizhiamumu/p/9451093.html [分页]:参考前文 ...
- 利用python的requests和BeautifulSoup库爬取小说网站内容
1. 什么是Requests? Requests是用Python语言编写的,基于urllib3来改写的,采用Apache2 Licensed 来源协议的HTTP库. 它比urllib更加方便,可以节约 ...
- phantomjs+selenium实现爬取动态网址
之前使用 selenium + firefox驱动浏览器来实现爬取动态网址,但是firefox经常更新,更新后时常会导致webdriver启动不来,所以改用phantomjs+selenium来改善一 ...
随机推荐
- 关于Sprites的一些理解
今天做测试,遇到一道选择题. 瞬间一脸懵逼,sprites是什么?通过对各选项的分析,大致明白了几点:1.它是css属性.2.它与图片有关.3.它是背景图片.然后就选了一个大概不靠谱的,成功的选错了. ...
- 解决layui表单ajax提交回调函数不起作用问题的两种方式
最近想用layui开发一个论坛模板用的是fly-ui,才接触layui对其还不太熟悉.一个简单的登录就困扰了我很久.登录的form通过ajax提交回调函数老是不起作用.经过浪费了N多时间的调试,发现l ...
- JAVA有关位运算的全套梳理
一.在计算机中数据是如何进行计算的? 1.1:java中的byte型数据取值范围 我们最开始学习java的时候知道,byte类型的数据占了8个bit位,每个位上或0或1,左边第一位表示符号位,符号位如 ...
- 网络|N1盒子做旁路由刷OpenWRT系统(小白专用)
N1盒子做旁路由刷OpenWRT系统(小白专用) 为什么要用N1盒子 现如今新上市的路由器,市面上能买到的300元以内的路由器大多数都是双频(5G Hz和2.4G Hz)和几年前相比无论是速度还是性能 ...
- 代号为 Kyria 的 Manjaro Linux 19.0 系统正式发布
Xfce版本仍然是主打,此版本Xfce更新到4.14,并且主要致力于在桌面和窗口管理器上完善用户体验. KDE版本提供了功能强大.成熟且丰富的Plasma 5.17桌面环境,此版本进行了完全重新设计. ...
- 手动搭建webpack + vue项目之初体验
在使用vue做开发时,大部分人只会使用官方提供的脚手架搭建项目,脚手架虽然很好用,但想要成为一名优秀的前端开发者,webpack这一道坎是绕不开的,所以我们要学会脱离脚手架,利用webpack手动搭建 ...
- 【MVC】使用Jquery缓存数据
前言 最近接手优化页面加载的任务. 分析其中一个原因是菜单页面ajax异步加载,页面很大,但是除非权限更改或者切换角色,否则每次请求返回数据不变,这个完全可以放在客户浏览器内进行缓存. 分析 粗略一分 ...
- 为什么 String 是 immutable 类
二哥,你能给我说说为什么 String 是 immutable 类(不可变对象)吗?我想研究它,想知道为什么它就不可变了,这种强烈的愿望就像想研究浩瀚的星空一样.但无奈自身功力有限,始终觉得雾里看花终 ...
- node.js中http.respone.end方法概述
方法说明: 结束响应,告诉客户端所有消息已经发送.当所有要返回的内容发送完毕时,该函数必须被调用一次. 如果不调用该函数,客户端将永远处于等待状态. 语法: response.end([data], ...
- 使用 Pandas 的 to_excel() 方法来将多个 csv 文件合并到一个 xlsx 的不同 sheets 内
这几天在用 Python3 研究一个爬虫,最后一个需求是把爬下来的20+个csv文件整合到一个excel表里的不同sheets. 初版的核心代码如下: while year <= 2018: c ...