关于sql:实战用puppeteer-和puppeteercluster-获取某站所有有用链接

8次阅读

共计 3671 个字符,预计需要花费 10 分钟才能阅读完成。

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};
}

问题瞻望

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

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

正文完
 0