puppeteer 抖音二维码采集脚本
499
0
0
363天前
### Puppeteer 是什么
1.Puppeteer 是 Node.js 工具引擎
2.Puppeteer 提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome
3.Puppeteer 默认情况下是以 headless无界面 启动 Chrome 的,也可以通过参数控制启动有界面的 Chrome
4.Puppeteer 默认绑定最新的 Chromium 版本,也可以自己设置不同版本的绑定
### Puppeteer 能做什么
1.生成页面 PDF。
2.抓取 SPA(单页应用)并生成预渲染内容(即“SSR”(服务器端渲染))。
3.自动提交表单,进行 UI 测试,键盘输入等。
4.创建一个时时更新的自动化测试环境。使用最新的 JavaScript 和浏览器功能直接在最新版本的Chrome中执行测试。
捕获网站的 timeline trace用来帮助分析性能问题。
5.测试浏览器扩展。
###需求描述
基于puppeteer框架,根据特定的关键词,通过抖音web端检索功能,获取最新群二维码图片,然后再对二维码做有效性校验和文字识别。
###技术要点
1.非登录状态,抖音web检索数量10个以内,所以要保持脚本的登录状态
2.抖音对检索有风控机制,要避开风控,否则没法持续爬取
3.抖音检索内容不全是有效数据,要做前置筛选
4.脚本执行过程中可能遇到各种意外,需要有故障恢复机制
5.优化puppeteer,减少内存和磁盘占用
技术准备
1.node V14.16.1
2.依赖 puppeteer request 最新
创建browser,args是优化后的参数,减少内存和磁盘的占用
```
const browser = await puppeteer.launch({
headless: false,
args: [
"--disable-web-security",
"--disable-features=UserAgentClientHint",
"--disable-blink-features=AutomationControlled",
'--start-maximized',
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--no-first-run',
'--no-zygote',
'--disable-gpu',
'--aggressive-cache-discard',
'--disable-cache',
'--disable-application-cache',
'--disable-offline-load-stale-cache',
'--disable-gpu-shader-disk-cache',
'--media-cache-size=0',
'--disk-cache-size=0'
],
defaultViewport: { width: 780, height: 1000 },
ignoreDefaultArgs: ["--enable-automation"],
ignoreHTTPSErrors: true,
// devtools: true,
executablePath: "./puppeteer/win64-1045629/chrome-win/chrome.exe"
});
```
header 通过抓包获取,完全复制过来即可
```
await page.setExtraHTTPHeaders({
"accept-encoding": "gzip, deflate, br",
"accept-language": "zh-CN,zh;q=0.9",
"sec-fetch-dest": 'document',
"sec-fetch-mode": "navigate",
"sec-fetch-site": "none",
"sec-fetch-user": "?1",
"upgrade-insecure-requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
});
```
登录状态保持,其实就是携带正常登录的cookie即可,可以自己抓下
```
let cookies = [];
str.split(';').map((value, index) => {
let key = value.split('=');
let item = {};
item['domain'] = '.douyin.com';
item['name'] = key[0].replace(' ', '');
item['value'] = key[1] ? key[1].replace(' ', '') : '';
item['path'] = '/';
cookies.push(item);
});
cookies.map(async (value) => {
await page.setCookie(value)
})
```
核心提取代码,需要针对异常情况做退出,进行下一个关键词的检索
轮训逻辑
```
let keywords = new Array('创业群', '广告群', '微商群', '兼职群', '求职群', '招聘群', '同城群', '交友群', '电商群', '学生群', '宝妈群', '娱乐群', '相亲群', '拼车群', '砍价群', '美女群', '商业群', '旅游群', '车友群', '公益群', '淘客群', '红包群', '影视群', '宠物群', '美妆群', '产品群', '互阅群', '投票群');
//let keywords = new Array("车友群");
let i = 0;
while (true) {
if(!isValidTime()){
await delay(60000*10)
continue;
}
let keyword = keywords[i % keywords.length];
i++;
let url = "http://www.douyin.com/search/" + keyword + "?publish_time=1&sort_type=0&source=tab_search&type=general";
console.info("keyword:" + keyword + " start search ");
try {
await page.goto(url, { timeout: 20000 });
await page.evaluate(async () => {
Object.defineProperty(navigator, "webdriver", { get: () => false });
});
let data = await doCrawler(page, 60);
if (data) {
console.info("++++++++++++++++:" + data.urls.length);
let formData = { urls: data.urls.join(), keywords: encodeURI(keyword) }
if (data.urls.length > 0) {
request.post({
url: "http://xx.threeperson.com/dy/qrcode/upload", formData: formData, headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
}
}
console.info("keyword:" + keyword + " end search size:" + (data)?data.urls.length:0);
} catch (error) {
console.info(keyword + " search open fail" + error);
continue;
} finally {
let mills = random(60000, 60000*2)
await delay(mills);
}
}
```
抓取逻辑
```
async function doCrawler(page, limit) {
let data = new Data();
let imageList = await page.waitForSelector(".aCTzxbOJ")
if (imageList == null) {
console.info("出现无搜索内容,退出当前任务");
return null;
}
while (data.total <= limit) {
try {
await delay(3000);
let noResult = await page.$("[class='P6wJrwQ6']")
if (noResult != null) {
console.info("无搜索内容,退出当前任务");
return;
}
noResult = await page.$("[class='Bllv0dx6']")
if (noResult != null) {
console.info("暂时没有更多,退出当前任务");
return;
}
let evalData = await page.evaluate((data) => {
let items = Array.from(document.querySelectorAll(".aCTzxbOJ"));
if (items == null || items.length <= data.total) {
console.info("images is empty 1");
return null;
}
let subItems = items.slice(data.total, -1);
data.total = items.length;
subItems.forEach(item => {
let textElement = item.querySelector(".EpX3I1jb");
let imgeElement = item.querySelector(".yWm90O3y");
if (null == imgeElement) {
return;
}
if (!imgeElement.src.includes(".webp")) {
return;
}
let text = textElement.innerText;
// 大概率过滤过期的二维码
if (text.includes("小时前") || text.includes("昨天") || text.includes("1天前") ) {
data.urls.push(imgeElement.src);
}
});
return data;
}, data);
if (evalData) {
data.addUrls(evalData.urls).addTotal(evalData.total);
}
await scroll(page);
//太快容易风控
let mills = random(3000, 5000)
await delay(mills);
} catch (err) {
console.error("data crawler fail" + err);
}
}
return data;
}
```
辅助类和函数
```
class Data {
urls = new Array();
total = 0;
addUrls(urls) {
if (null == urls || urls.length <= 0) {
return this;
}
urls.forEach(url => this.urls.push(url));
return this;
}
addTotal(total) {
this.total += total;
return this;
}
}
function isEmpty(val) {
let isArray = typeof val;
if (undefined === val || null === val || "" === val || (isArray && val.length == 0)) {
return true;
}
return false;
}
async function scroll(page) {
await page.evaluate(() => {
window.scrollBy(0, 800)
})
}
function isValidTime(){
let now = new Date()
let hour = now.getHours()
if(hour>8 && hour< 20){
return true;
}
return false;
}
```
### 执行情况
```
PS G:\html5_workspace\dy-qrcode> node .\main.js
keyword:创业群 start search
++++++++++++++++:6
6
keyword:广告群 start search
++++++++++++++++:10
10
keyword:微商群 start search
暂时没有更多,退出当前任务
微商群 search open failTypeError: Cannot read property 'urls' of undefined
```
### 提取数据
```
https://p3-pc-sign.douyinpic.com/tos-cn-i-0813/0dd09556f8fd497eb3d64577f5969f50~q75.webp?biz_tag=aweme_images&from=3213915784&s=PackSourceEnum_SEARCH&se=false&x-expires=1672801200&x-signature=cddg7plaBJtPTEJyrvBz3dUgppk%3D
```