nodejs抓取动态网页(puppeteer和nodejs的区别)

优采云 发布时间: 2022-01-16 19:05

  nodejs抓取动态网页(puppeteer和nodejs的区别)

  傀儡师

  google chrome 团队出品的 puppeteer 是一个依赖 nodejs 和 chromium 的自动化测试库。它最大的优点是可以处理网页中的动态内容,例如JavaScript,以更好地模拟用户。

  一些网站的反爬方法隐藏了一些javascript/ajax请求中的部分内容,使得直接获取a标签的方法不起作用。甚至一些 网站 会设置隐藏元素“陷阱”,对用户不可见,脚本将其作为机器触发。在这种情况下,puppeteer的优势就凸显出来了。

  它可以实现以下功能:

  生成页面的屏幕截图和 PDF。抓取 SPA 并生成预渲染内容(即“xxxx”)。自动提交表单、UI测试、键盘输入等。创建最新的自动化测试环境。使用最新的 JavaScript 和浏览器功能直接在最新版本的 Chrome 中运行测试。捕获跟踪您的 网站 的时间线以帮助诊断性能问题。

  开源地址:[][1]

  安装

  npm i puppeteer

  注意先安装nodejs,在nodejs文件的根目录下执行(与npm文件同级)。

  安装过程中会下载chromium,大约120M。

  经过两天(大约10个小时)的探索,绕过了很多异步的坑,作者对puppeteer和nodejs有一定的把握。

  长图,抢博客文章列表:

  

  爬博客文章

  以csdn博客为例,文章的内容需要通过点击“阅读全文”获取,使得只能阅读dom的脚本失效。

  /**

* load blog.csdn.net article to local files

**/

const puppeteer = require('puppeteer');

//emulate iphone

const userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1';

const workPath = './contents';

const fs = require("fs");

if (!fs.existsSync(workPath)) {

fs.mkdirSync(workPath)

}

//base url

const rootUrl = 'https://blog.csdn.net/';

//max wait milliseconds

const maxWait = 100;

//max loop scroll times

const makLoop = 10;

(async () => {

let url;

let countUrl=0;

const browser = await puppeteer.launch({headless: false});//set headless: true will hide chromium UI

const page = await browser.newPage();

await page.setUserAgent(userAgent);

await page.setViewport({width:414, height:736});

await page.setRequestInterception(true);

//filter to block images

page.on('request', request => {

if (request.resourceType() === 'image')

request.abort();

else

request.continue();

});

await page.goto(rootUrl);

for(let i= 0; iwindow.scrollTo(0, document.body.scrollHeight));

await page.waitForNavigation({timeout:maxWait,waitUntil: ['networkidle0']});

}catch(err){

console.log('scroll to bottom and then wait '+maxWait+'ms.');

}

}

await page.screenshot({path: workPath+'/screenshot.png',fullPage: true, quality :100, type :'jpeg'});

//#feedlist_id li[data-type="blog"] a

const sel = '#feedlist_id li[data-type="blog"] h3 a';

const hrefs = await page.evaluate((sel) => {

let elements = Array.from(document.querySelectorAll(sel));

let links = elements.map(element => {

return element.href

})

return links;

}, sel);

console.log('total links: '+hrefs.length);

process();

async function process(){

if(countUrl {

if (request.resourceType() === 'image')

request.abort();

else

request.continue();

});

await tab.goto(url);

//execute tap request

try{

await tab.tap('.read_more_btn');

}catch(err){

console.log('there\'s none read more button. No need to TAP');

}

let title = await tab.evaluate(() => document.querySelector('#article .article_title').innerText);

let contents = await tab.evaluate(() => document.querySelector('#article .article_content').innerText);

contents = 'TITLE: '+title+'\nURL: '+url+'\nCONTENTS: \n'+contents;

const fs = require("fs");

fs.writeFileSync(workPath+'/'+tab.url().substring(tab.url().lastIndexOf('/'),tab.url().length)+'.txt',contents);

console.log(title + " has been downloaded to local.");

await tab.close();

}catch(err){

console.log('url: '+tab.url()+' \n'+err.toString());

}finally{

process();

}

}

})();

  实施过程

  录屏可以在我的公众号查看,截图如下:

  

  结果

  文章内容列表:

  

  文章内容:

  

  结束语

  之前我想既然nodejs使用的是JavaScript脚本语言,那么它一定能够处理网页的JavaScript内容,但是我还没有找到一个合适/高效的库。直到我找到了 puppeteer,我才决定试水。

  说了这么多,nodejs的异步性真是让人头疼。这几百行代码我折腾了10个小时。

  您可以在代码中展开 process() 方法并使用 async.eachSeries。我使用的递归方法不是最佳解决方案。

  事实上,一个一个地处理是没有效率的。本来我写了一个异步关闭浏览器的方法:

<p>let tryCloseBrowser = setInterval(function(){

console.log("check if any process running...")

if(countDown

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线