本篇文章针对大家熟知的技术站点作为目标进行技术实践。
确定需求
访问目标网站并按照筛选条件(关键词、日期、作者)进行检索并获取返回数据中的目标数据。进行技术拆分如下:
- 打开目标网站
- 找到输入框元素输入关键词,找到日期元素设置日期,找到搜索按钮触发搜索动作
- 解析搜索返回的html元素构造目标数据
- 将目标数据保存
编写代码
'use strict';
const puppeteer = require('puppeteer');
const csv = require('fast-csv');
const fs = require('fs');
(async () => {
const startUrl = 'https://www.infoq.cn/';
const keyWord = 'CQRS';
const browser = await puppeteer.launch({
slowMo: 100, // 放慢速度
headless: false, // 是否有头
defaultViewport: {// 界面设置
width: 1820,
height: 1080,
},
ignoreHTTPSErrors: false, // 忽略 https 报错
args: ['--start-maximized', '--no-sandbox', '--disable-setuid-sandbox'],
});
const page = await browser.newPage();
await page.goto(startUrl).catch(error => console.log(error));
await page.waitFor(1 * 1000);
await page.click('.search,.iconfont');
await page.type('.search-input', keyWord, { delay: 100 });
const newPagePromise = new Promise(x => browser.once('targetcreated', target => x(target.page())));
await page.click('.search,.iconfont');
const targetPage = await newPagePromise;
const dataCount = await targetPage.$eval('.search-body-main-tips span', el => el && el.innerHTML).catch(error => console.error(error));
if (dataCount && dataCount > 0) {
const dataEle = await targetPage.$$('.search-item');
console.log(dataEle.length);
const stream = fs.createWriteStream('infoq.csv');
const csvStream = csv.format({ headers: true });
csvStream.pipe(stream).on('end', process.exit);
for (let index = 0; index < dataEle.length; index++) {
const element = dataEle[index];
const title = await element.$eval('a', el => el && el.innerHTML).catch(error => console.error(error))
const desc = await element.$eval('.desc', el => el && el.innerHTML).catch(error => console.error(error))
csvStream.write({
标题: title || '',
摘要: desc || '',
});
}
csvStream.end(() => { console.log('写入完毕'); });
}
await targetPage.screenshot({ path: 'infoq.png' });
await browser.close();
})();
具体的如下
总结
上面的例子还是比较简单的,站点本身是资讯站(其实有搜索接口根本不需要解析html