threeperson
发布于 2022-12-05 / 0 阅读
0
0

puppeteer 抖音二维码采集脚本

### 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

```


评论