puppeteer + cheerio + mysql 模拟用户去爬取一个aspx网站
# 起源
最近被前同事问是否可以帮他去爬取一个网站的数据,然后他把网站发给我了,之后我就去研究了下,
本来计划用spider-flow 这个东西来爬的,毕竟能不写代码的,为啥我要去写代码,然后研究了下spider-flow 发现满足不了需求,浪费了两天时间, 😄😄😄, 还是老老实实手写把,对spider-flow 感兴趣的可以看看我写的:https://www.mubucm.com/doc/7rBgfYhSzrt (opens new window)
# 最终效果
# 作者在写这篇文章的技能和环境
- 前端略懂一二
- nodejs 一窍不通
- 数据库一窍不通
- window系统
- puppeteer 版本: 19.7.4
- node版本: 14.18.0
# 本文只适合小白阅读,大佬请出门左转~
# 页面地址
# 页面分析
- 一手房预售信息页面信息首页数据从哪里来?
- 页面执行逻辑
- 页面渲染逻辑
# 思路
- 思路1:模拟用户操作,像一个正常的用户去点击然后爬取数据,之后再把数据存储到数据库, 然后点击分页重复这个操作,直到爬取完所有数据
- 思路2:直接调用获取数据接口,然后解析数据,之后再把数据存储到数据库我们先用思路1的方式来做,
- 本来我想用思路2的做法来做,后来有个问题没解决,所以先按照思路1来实现
# 核心代码讲解
# puppetter 如何改变页面的值?
# 官网api
- 具体代码,按照20条/页去爬取
# puppetter 如何触发事件?
- api
- 实例:
page.click(#AspNetPager1 > span:nth-last-of-type(1), {delay: 100})
1
# 使用puppetter访问页面,如何去解析数据?
- 一开始我还一直被困在这个puppetter api,一直想在这个浏览器执行的时候去获取这些信息,其实这种也是可以的,但是不方便,后来百度发现可以使用cheerio这个库,像使用jquery把对页面做操作
- cheerio 遍历页面数据
- cheerio 具体代码
# 如何把保存数据到数据库?新建一个house_info 数据库,然后搞了一个presell 预售表,预售的表结构
# sql相关知识查询数据
- select * from presell
- 更新某一条数据:update presell set name='阿斯顿撒',enterprise=99 WHERE serial=2
- 更新所有的数据:UPDATE presell SET address='深圳'插入数据:INSERT INTO presell (mainKey,serial,id) VALUES (1111,2,3);
- 批量插入数据:INSERT INTO presell ( mainKey, serial, id, NAME, enterprise, address, date ) VALUES ( '10001', '2', '3', '4', '5', '6', '2022-02-06' ),( '10002', '2222', '3', '4', '5', '6', '2022-02-06' )
# 如何批量插入数据
var mysql = require('mysql2');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'root'
});
connection.query('use house_info')
const array = [
[
1679389969116,
'13',
'深房许字(2023)南山003号',
'http://zjj.sz.gov.cn/ris/bol/szfdc/certdetail.aspx?id=126737',
'方直珑樾山花园',
'http://zjj.sz.gov.cn/ris/bol/szfdc/ojectdetail.aspx?id=126737',
'深圳市龙廷房地产开发有限公司',
'南山',
'2023-03-02'
],
[
1679389969118,
'13',
'深房许字(2023)南山003号',
'http://zjj.sz.gov.cn/ris/bol/szfdc/certdetail.aspx?id=126737',
'方直珑樾山花园',
'http://zjj.sz.gov.cn/ris/bol/szfdc/ojectdetail.aspx?id=126737',
'深圳市龙廷房地产开发有限公司',
'南山',
'2023-03-02'
],
]
connection.query(`INSERT INTO presell ( mainKey, serial, idCard, idCardUrl, productName, productUrl, enterprise, location, authorizeDate )
VALUES ?`,[array], function (error, results, fields) {
if (error) {
log.error('批量插入失敗,错误信息==>', error)
throw error;
}
// connected!
log.info('批量插入成功', results)
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 开始编码
- puppetter 环境搞了我两天,装了新版本,chrom一直没有下载下来,😭😭😭,解决方法看后面
# 先访问一次
# 因为第一组分页的页面结构和第二组的页面结构不一样,所以要搞成不同的逻辑不同的页面结构,难搞哦
# 第一页的时候的页面结构和逻辑
# 第二组分页的页面机构和逻辑
# 开始第一轮的轮询
# 开始第二轮的轮询
# 存储数据库的逻辑
# 下载不了chromium的解决办法
# Failed to set up Chromium r1095492! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to skip download
# 问题截图 关键词:Failed to set up Chromium r1095492! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to skip download
# 问题原因: 下面这张图是我在家里面直接更新就好了,一点问题都没有,在公司电脑已更新就狗带,太难了
# 解决办法:(想直接看答案的,直接跳到终极原因 或者方法5处查看解决办法)
# 方法1: 从puppeteer 源码找到下载的资源
- 修炼不到家,找不到,😄😄😄,后来就放弃了
# 方法2:从chromium 官网下载对应的版本
- 查看puppeter和chromium的对应关系,找到对应关系 然后在chromium的下载链接后面自己换一下,然后下载https://github.com/chromium/chromium/releases/tag/111.0.5556.0 (opens new window)
-等了两个小时,发现这个文件是不对的,700m,家里面那个电脑也就是170m。这个思路也是错的
- 查看puppeter和chromium的对应关系,找到对应关系 然后在chromium的下载链接后面自己换一下,然后下载https://github.com/chromium/chromium/releases/tag/111.0.5556.0 (opens new window)
# 方法3:chrome与puppeteer版本发生冲突在gitee上找了另一个思路
- 我当时找到了这个issue,但是没有按照这个思路找下去,如果我直接去搜索这个关键词,可能我就不用浪费半天时间了。哈哈谷歌搜索这个关键词
- 看这里,github地址: https://github.com/wadezhan/billfeller.github.io/issues/232,是个深圳的大佬,感谢~ (opens new window)
# 方法4:puppeteer install Chromium r1095492 error换了个思路,然后进了这个网站
- 看了这个issue:https://github.com/puppeteer/puppeteer/issues/1597#issuecomment-351945645 (opens new window)
- 2017年这个问题就存在了,只不过那时候大多数人用了淘宝镜像可以解决,但是我在2023-03-13的时候用淘宝镜像就发现没有那个资源,应该是没有同步过来
- cnpm 也有这个问题
- Download failed: server returned code 404. URL: https://npmmirror.com/mirrors//chromium-browser-snapshots/Win_x64/1095492/chrome-win.zip (opens new window)
- chromium-browser-snapshots库
# 终极原因
我就一直好奇这个Failed to set up Chromium r1095492! 里面的r1095492是啥东西,后来得到答案才知道,原来是一个所谓的版本号。。。,我一直以为是chromium 的版本,思路错了,他是一个chromium-browser-snapshots 里面的版本号 https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/ (opens new window)
- 这个没有梯子上不去:https://registry.npmmirror.com/binary.html?path=chromium-browser-snapshots/Win_x64/ (opens new window)
https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1095492/ (opens new window)
-下载后的资源大概长这样,两天了,你知道我两天怎么过来的吗!!!
- 直接把解压后的文件丢上去是不行的,必须按照puppeter 的这种格式才行,解压出来是chrome-win文件夹,
- 然后把拷贝的文件,丢到当前用户下的 .cache/puppeteer 下新建一个win64-1095492文件夹下就好了
- 搞定,下班!!!
- 最后,总结一下,其实自己好多次都已经触碰到了答案,只是没有注意到,😄😄,历时两天,终于搞定,感谢阅读,谢谢~
# 方法5:使用本机的chrom
- 第一步:export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
- 第二步:npm i puppeteer
- 第三步:https://stackoverflow.com/questions/59786319/configure-puppeteer-executablepath-chrome-in-your-local-windows (opens new window)
await puppeteer.launch({ headless: false, args: ['--disable-infobars', '--no-sandbox', '--disable-setuid-sandbox'], // window 如果复制是下面的地址是不行的, executablePath: 'C:\Program Files\Google\Chrome\Application\chrome.exe', // window 要把 地址里面的 \ 都变成 \ \ ,不然狗带,忘记是啥原因了,反正就是没有计算机体系知识不懂,哈哈,大概这种意思 executablePath: 'C:\Program Files\Google\Chrome\Application\chrome.exe', });
1
# 想看源码的可以瞅瞅
# 免责声明
- 本项目只是学习使用,无意对此网站进行爬虫等操作
# 参考资料
- puppeteer如何触发表单提交
- puppeteer如何执行页面的js方法
- Puppeteer 基本概念介绍 (opens new window)
- puppeteer环境部署问题小记 (opens new window)
- vscode 如何调试node
// launch.json 配置
{
"name": "nodejs-debugger",
"program": "${workspaceFolder}/index.js",
"request": "launch",
"skipFiles": [
"<node_internals>/**"
],
"type": "node"
},
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- 数据库相关date空字符串处理问题原因,爬了一千多条数据,然后挂了,说插入数据库错误。。。
问了下大哥们,好像不行,只能传入date 和null,或者是说把date 变成字符串,哈哈,感觉不好把,有点业余
上次更新: 2023/12/18, 15:00:26
- 01
- 若依3.8.5版本vue-cli升级到 5.0.8碰到的一些问题10-08
- 02
- vuepress添加sitemap05-17
- 03
- vscode Live Server 插件使用教程05-16