【问题标题】:Scraping carousell with puppeteer用 puppeteer 刮旋转木马
【发布时间】:2020-01-10 10:08:57
【问题描述】:

我目前正在做一个项目,需要从 carousell.ph 中的搜索结果中抓取数据

我基本上制作了一个示例 HTML 并复制了 carousell 的输出 HTML,到目前为止,javascript 工作正常,除非我尝试使用 puppeteer 迁移它,但它总是给我一个错误。

任务基本上是从搜索网址“https://www.carousell.ph/search/iphone”中获取所有产品列表

这是我编写的代码。

const puppeteer = require('puppeteer');
(async () => {

    const browser = await puppeteer.launch()
    const page = await browser.newPage()

    let url = 'https://www.carousell.ph/search/iphone';
    await page.goto(url, {waitUntil: 'load', timeout: 10000});
    await page.setViewport({ width: 2195, height: 1093 });
    await page.screenshot({ fullPage: true, path: 'carousell.png' });
    document.querySelectorAll('main').forEach(main => {
        main.querySelectorAll('a').forEach(product => {
            const product_details = product.querySelectorAll('p');
            const productName = product.textContent;
            const productHref = product.getAttribute('href');
            console.log(product_details[0].textContent + " - "+ product_details[1].textContent);
        });
    });

    await browser.close()

})()

【问题讨论】:

  • 错误是什么?
  • node:8980) UnhandledPromiseRejectionWarning: ReferenceError: 文档未定义 (node:8980) UnhandledPromiseRejectionWarning: 未处理的承诺拒绝。此错误源于在没有 catch 块的情况下抛出异步函数内部,或拒绝未使用 .catch() 处理的承诺。 (拒绝 ID:1)(节点:8980)[DEP0018] DeprecationWarning:不推荐使用未处理的承诺拒绝。将来,未处理的 Promise 拒绝将使用非零退出代码终止 Node.js 进程。
  • 如果你想在浏览器中执行代码,你应该使用evaluate函数。这就是为什么没有定义文档的原因,因为你在节点端。

标签: puppeteer


【解决方案1】:

正如@hardkoded 所说,document 在 puppeteer 中不是开箱即用的东西,它是浏览器中的教条,但在 Node.js 中不是。您也不需要在 Node.js 中为每个。 this video 中概述的地图技术非常有用且快速。我还要确保在您的循环或映射技术上保持等待,因为该函数是异步的,所以您要确保承诺得到解决。

地图技术

从页面中将许多元素放入数组中的一种极快的方法是使用如下所示的函数。因此,不要获取元素数组,然后循环它们以获得它们的属性。您可以使用 $$eval 和 map 创建如下所示的函数。结果是一个格式化的 JSON 数组,它将所有循环都排除在等式之外。

const links = await first_state_list.$$eval("li.stateList__item", links =>
      links.map(ele2 => ({
        State_nme: ele2.querySelector("a").innerText.trim(), //GET INNER TEXT
        State_url: ele2.querySelector("a").getAttribute("href") //get the HREF
      }))
    );

【讨论】:

    【解决方案2】:

    已经成功了。

    const puppeteer = require('puppeteer');
    
    async function timeout(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    (async () => {
    
        const browser = await puppeteer.launch()
        const page = await browser.newPage();
    
        let searchItem = 'k20&20pro';
        let carousellURL = 'https://www.carousell.ph/search/' + searchItem;
        await page.goto(carousellURL, {waitUntil: 'load', timeout: 100000});
        //await page.goto(carousellURL, {waitUntil: 'networkidle0'});
        await page.setViewport({ 
            width: 2195, 
            height: 1093 
        });
        await page.evaluate(() => {
            window.scrollBy(0, window.innerHeight);
        })
        await timeout(15000);
        await page.screenshot({ 
            fullPage: true, 
            path: 'carousell.png' 
        });
    
        var data = await page.evaluate(() =>
            Array.from(
                document.querySelectorAll('main div a:nth-child(2)')).map(products => products.href
            )
        )
    
        var i;
        for (i = 0; i < data.length; i++) { 
            console.log(data[i]);
            // comment this section but this will open the page to get product details.
            //await page.goto(data[1], {"waitUntil" : "networkidle0"});
    
            // inner product page details
            // this will get the title
            // document.querySelectorAll('h1')[0].innerText;
            // this will get the amount
            // document.querySelectorAll('h2')[0].innerText;
            // this will get the description
            // document.querySelectorAll('section div div:nth-child(4) p')[0].innerText;
            // this will get sellers name
            // document.querySelectorAll('div div:nth-child(2) a p')[0].innerText;
    
            let ss_filename = 'carousellph_'+searchItem+'_'+i+'.png';
            console.log(ss_filename);
            console.log("\r\n");
            //await page.screenshot({ fullPage: false, path: ss_filename });
        }
    
        await browser.close()
    
    })()
    

    【讨论】:

    • 太好了,因为您使用了技术中的地图数组,您能接受答案吗:)?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-01
    • 1970-01-01
    • 2021-01-27
    • 2012-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多