puppeteer

谷歌推出的用于操作无头浏览器的nodeJs框架,提供下层API用于间接操作浏览器。该框架实用于爬取web2.0页面,同时对web1.0的支持率也比拟高,代码编写也很简略。
puppeteer中文文档

Puppeteer-cluster

池化思维作用于puppeteer的产物,工作散发与调度,让nodejs能够利用自身去实现整个爬虫。在应用该组件之前,我应用java来写爬虫的调度算法,而后用eureka来调用nodejs的页面抓取模块。
puppeteer-cluster我的项目地址

首先须要获取整站的所有页面

获取所有页面,并确定当url是pan.baidu.com的时候过滤掉曾经生效的链接

const {Cluster} = require('puppeteer-cluster');const launchOptions = {    headless: true,    ignoreHTTPSErrors: true,        // 疏忽证书谬误    waitUntil: 'networkidle2',    defaultViewport: {        width: 1920,        height: 1080    },    args: [        '--disable-gpu',        '--disable-dev-shm-usage',        '--disable-web-security',        '--disable-xss-auditor',    // 敞开 XSS Auditor        '--no-zygote',        '--no-sandbox',        '--disable-setuid-sandbox',        '--allow-running-insecure-content',     // 容许不平安内容        '--disable-webgl',        '--disable-popup-blocking',        //'--proxy-server=http://127.0.0.1:8080'      // 配置代理    ],    executablePath: 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',};const clusterLanuchOptions = {    concurrency: Cluster.CONCURRENCY_PAGE,  // 单Chrome多tab模式    maxConcurrency: 20,  // 并发的workers数    retryLimit: 2,   // 重试次数    skipDuplicateUrls: true,  // 不爬反复的url    monitor: true,  // 显示性能耗费    puppeteerOptions: launchOptions,};(async () => {    const cluster = await Cluster.launch(clusterLanuchOptions);    const cluster2 = await Cluster.launch(clusterLanuchOptions2);    await cluster2.task(async ({page, data: url}) => {        let urlTrue = url.split(' ')[0];        await page.goto(urlTrue);        await page.waitForSelector('html');        let title = await page.title();        let x = "D:\\workspace\\node\\check\\bbs\\controllers\\pantrue.txt";        if (title.indexOf('不存在') === -1) {            let value = '';            if (title.indexOf('分享无限度')) {                value = urlTrue + ' ' + title + '\n';            } else {                value = url.split(' ')[1].substr(0, 20) + ' ' + url.split(' ')[2] + ' ' + urlTrue + ' ' + title + '\n';            }            fs.writeFile(x, value, {flag: 'a'}, function (err) {                if (err !== null) {                    console.log(err);                }            });        }    });    await cluster.task(async ({page, data: url}) => {        await page.goto(url);        await page.waitForSelector('html');        let title = await page.title();        await page.content();        let x = "D:\\workspace\\node\\check\\bbs\\controllers\\pan.txt";        let y = "D:\\workspace\\node\\check\\bbs\\controllers\\outDomain.txt";        let yuanDomain = urllib.parse(urlTrue);        let newDomain = urllib.parse(url);        if (yuanDomain.hostname !== newDomain.hostname) {            if (!outUrlSet.has(newDomain.hostname)) {                fs.writeFile(y, url + ' ' + title + '\n', {                    flag: 'a'                }, function (err) {                    if (err) {                        console.error(err);                    }                });                outUrlSet.add(newDomain.hostname);            }        } else {            let links = await page.$$eval('[src],[href],[action],[data-url],[longDesc],[lowsrc]', get_src_and_href_links);            let res = await parseLinks(links, url);            console.log({links: links.length}, {res: res.length});            for (let i = 0; i < res.length; i++) {                let link = res[i];                if (link !== undefined && link.indexOf("pan.baidu.com") !== -1) {                    // todo 存起来                    if (!panSet.has(link)) {                        fs.writeFile(x, link + ' ' + title + ' ' + url + '\n', {                            flag: 'a'                        }, function (err) {                            if (err) {                                console.error(err);                            }                        });                        cluster2.queue(link + ' ' + title + ' ' + url);                        panSet.add(link);                    }                } else {                    cluster.queue(link);                }            }        }    });    cluster.queue('http://www.xxxxx.com/');    await cluster.idle();    await cluster.close();})();async function parseLinks(links, url) {    let result = [];    // 解决url    return result;}function get_src_and_href_links(nodes) {    let result = [];    // 获取节点中的所有    return result;}

剖析页面,获取更深的信息

失去的盘链接,有些是无限度的,有些是须要tiquma的,而tiquma该如何获取呢?往往原来的页面外面会有,这个时候咱们就须要剖析原来的页面了。

在这个网站中,提取码简直都放在strong标签中,那咱们只好应用办法失去页面中的strong标签
在puppeteer中能够应用page.$$eval()办法来获取strong节点汇合,而后应用treeWalker遍历整个节点失去咱们想要的货色即可。

let {text,html} = await page.$$eval('strong', getTiQuMa);function getTiQuMa(nodes) {    let html = '';    let text = '';    for (let node of nodes) {        let treeWalker = document.createTreeWalker(            node,            NodeFilter.SHOW_ELEMENT,            {                acceptNode: function (node1) {                    return NodeFilter.FILTER_ACCEPT;                }            },            false        );        while (treeWalker.nextNode()) {            let element = treeWalker.currentNode;            text = text + ' ' + element.innerText;        }    }    return {text: text, html: html};}

问题瞻望

当初,咱们实现了基于一个网站的所有盘链接的获取,那么,如果当初想要实现一个通用的盘链接获取爬虫,从而实现盘链接的搜索引擎该如何实现呢?
关注我,让我给你解答。

炒鸡辣鸡原创文章,转载请注明起源