使用Puppeteer抓取受限网站

不要相信前端是安全的,今天简单验证一下,但是希望大家支持正版,支持原作者,毕竟写书不易。

安装Puppteer

1
npm install --save puppeteer

选择目标网站

我们这里选择胡子大哈大神的网站 http://huziketang.mangojuice.top
爬取所有文章

基本思想思路

  • 实现方案

爬取书籍目录->根据目录爬取没个章节的内容

  • 注意的地方

本书有付费章节和免费章节,爬取付费章节需要禁用javascript执行,然后移除对应的mask的dom节点

核心代码

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
const path = require('path');
const fs = require('mz/fs');
const puppeteer = require('puppeteer');


const pdfDir = path.resolve(__dirname, './pdf/');
const targetHost = "http://huziketang.mangojuice.top"


//保存pdf 文件
const savePdf = async (page, link) => {
let fileName = link.substring(link.lastIndexOf('/')) + '.pdf';
await page.goto(link);
await page.evaluate(() => {
//隐藏左侧菜单栏 以及下方部分内容
let allNeedHidens = document.querySelectorAll('#table-of-content,.PageNavigation,.share-block,hr,blockquote,.post__back>a,#wrapper>h1');
let elCount = allNeedHidens.length;
for (let i = 0; i < elCount; i++) {
allNeedHidens[i].style.display = 'none';
}
});
await page.pdf({
path: pdfDir + fileName
});
console.log(`${link} saved to pdf successfully!!!`);
}



//启动程序
const start = async () => {
//创建一个browser 实例
let browser = await puppeteer.launch({
headless: true,
devtools: false
});

//创建一个空白page实例
let page = await browser.newPage();
//设置禁用js,当前必须设置,否则会导致页面无法处理
//说明:只是禁用page原有javascript,但是page.evaluate 中可以继续使用
await page.setJavaScriptEnabled(false);

//获取书目录标题
await page.goto(targetHost + '/books/react/');

let result = await page.evaluate((targetHost) => {
//获取目录链接
let ulArray = document.querySelectorAll('ul.table-of-content>li>a');
let array = Array.prototype.slice.call(ulArray, 0);
let links = array.map((v) => {
let href = v.getAttribute('href');
return `${targetHost}${href}`;
})
return {
links: links
}
}, targetHost);

for (let link of result.links) {

await savePdf(page, link);

}


await page.close();
await browser.close();


}

start();

代码比较简单,不做过多解释。