首页 > 解决方案 > 使用 Apify 的 Puppetetteer Crawler 抓取网站页面

问题描述

(*) 情况 :

你好 !

我想爬谷歌酒店平台,我点击一个城市,它会给我那个城市的所有酒店。例如纽约市的结果,它将为我们提供超过 1200 家酒店,所以我想抓取有关这些酒店的所有信息。

我使用了 Apify 的 Puppeteer Crawler,在开始 urls中,我放了第一页的 url。在链接选择器中,我把选择器转到了酒店详情页面。

这就是我在Page Function中输入的内容:

async function pageFunction(context) {
    
    const { request, log, skipLinks, page } = context;
   

    //request.userData = list_links;
    if (request.userData.label === 'START') {
        log.info('Store opened!');
       
    }

    if (request.userData.label === 'DETAIL') {
        const { url } = request;
        log.info(`Scraping ${url}`);
        await skipLinks();
        
        const titleP = page.$eval(
            'title',
            (el => el.textContent)
        );
       const priceP = page.$eval(
           'div.JGa7fd',
           (el => el.getAttribute('aria-label'))
       );
        const ratingP = page.$eval(
            'div.iDqPh.BgYkof',
            (el => el.textContent)
        );
        const reviewsNumberP = page.$eval(
            'a.eS7K5e',
            (el => el.textContent)
        );
        const hotelStarP = page.$eval(
            'div.fnmyY > span.CFH2De',
            (el => el.textContent)
        );
        const adressP = page.$$eval(
           'div.K4nuhf span.CFH2De',
           (els) => els[0].textContent
       ); 
       
        const phoneP = page.$$eval(
            'div.K4nuhf span.CFH2De',
            (els) => els[2].textContent

        );
        const websiteP = page.$$eval(
            'a.FKF6mc.TpQm9d',
            (els) => els[0].getAttribute('href')
        );

        
        const [
            title,
            price,
            rating,
            reviewsNumber,
            adress,
            phone,
            hotelStar,
            website,
            
        ] = await Promise.all([
            titleP,
            priceP,
            ratingP,
            reviewsNumberP,
            adressP,
            phoneP,
            hotelStarP,
            websiteP,
        ]);

    
        

        return {
            title,
            price,
            rating,
            reviewsNumber,
            adress,
            phone,
            hotelStar,
            website,
        };
    }
}

(*) 问题 :

如果您分析页面,您会发现它们不是枚举页面(第 1 页,第 2 页,第 3 页),我们只有 Next & Previous Button(即使您分析 URL,它也没有 "&page= 1/2/3" 或类似的东西,如果我们期望这个按钮(下一个按钮),我们会得到它是一个带有 role="button" 的 div 标签,并且没有任何 href 属性可供选择。

(*) 问题 :

1-如何使用 Puppeteer 抓取所有页面?如何转到下一页并刮掉它们?

2-我可以在 APify 中使用所有 puppeteer 文档,还是它们有一些限制?

3- Pure Puppeteer 和 Apify 的 Puppeteer 有什么区别?

(*) 半解:

对于问题 1,我尝试了这个解决方案,我使用 Pure Puppeteer,我转到第一页,单击下一步按钮,获取它的 url,再次转到下一页,获取它的 url,等等,直到完成 while环形 。之后,我将 url 复制粘贴到 txt 文件中,然后将其上传到启动 url。

这是我尝试过的代码源:

const puppeteer = require('puppeteer');

(async function main() {

  try {
    const browser = await puppeteer.launch({ headless: false });
    const [page] = await browser.pages();

    

    const url ="https://www.google.com/travel/hotels/Marrakesh?utm_campaign=sharing&utm_medium=link&utm_source=htls&hrf=CgUIzAgQACIDTUFEKhYKBwjkDxAIGBkSBwjkDxAIGBoYASABsAEAWAFoAYoBKAoSCcxMCO-rXT9AEQMTl9GnSCDAEhIJVRwqc-jwP0ARByaebVl8HsCaATESCU1hcnJha2VzaBokMHhkYWZlZThkOTYxNzllNTE6MHg1OTUwYjY1MzRmODdhZGI4ogEVCggvbS8wNTRydxIJTWFycmFrZXNoqgEbCgIIIRICCAgSAggVEgMIlAISAggvEgIIVBgBqgEHCgMIoQIYAKoBDAoDCLYBEgMIuAEYAaoBBgoCCGQYAKoBCgoCCC4SAghIGAGqAQwKAwiuARIDCLQBGAGqAQoKAghQEgIITxgBqgEMCgMIowESAwimARgBkgECIAE&rp=OAE&ap=KigKEgnMTAjvq10_QBEDE5fRp0ggwBISCVUcKnPo8D9AEQcmnm1ZfB7AMAFanwIKBQjMCBAAIgNNQUQqFgoHCOQPEAgYEhIHCOQPEAgYExgBKACwAQBYAWgBigEoChIJzEwI76tdP0ARAxOX0adIIMASEglVHCpz6PA_QBEHJp5tWXwewJoBMRIJTWFycmFrZXNoGiQweGRhZmVlOGQ5NjE3OWU1MToweDU5NTBiNjUzNGY4N2FkYjiiARUKCC9tLzA1NHJ3EglNYXJyYWtlc2iqARsKAgghEgIICBICCBUSAwiUAhICCC8SAghUGAGqAQcKAwihAhgAqgEMCgMItgESAwi4ARgBqgEGCgIIZBgAqgEKCgIILhICCEgYAaoBDAoDCK4BEgMItAEYAaoBCgoCCFASAghPGAGqAQwKAwijARIDCKYBGAGSAQIgAQ"
    await page.goto(url,{
        waitUntil: 'load',
        // Remove the timeout
        timeout: 0});

  
    //for(i=0;i<10;i+)
    console.log(url);
    console.log('\n');
    while(true){
        await page.click('div.zbLWdb');
        await page.waitFor(30*1000);
        var new_link = page.url();
        
        console.log(new_link);
        console.log('\n\n');
        i++;
    }

    
  } catch (err) {
    console.error(err);
  }
})();

我可以把这个脚本放在开始网址中吗?如何做到这一点?

标签: javascriptjquerypuppeteercheerioapify

解决方案


我不会为您提供成功抓取它的所有详细信息,但会给您一些提示。

a) 获得正确的名称很重要。在这种情况下,您使用的是Puppeteer Scraper。那是一个独立的演员。PuppeteerCrawler是 SDK(JS 库)中的一个类。

b) 链接选择器不会点击,它需要找到hrefs(真正的链接)。所以它不适用于这个用例。

c) 在这种情况下,我建议使用 PuppeteerCrawler 类创建一个新参与者(请参阅SDK站点中的示例)。

现在回答你的问题:

  1. 你可以在 Apify 中使用你的代码,它的工作原理是一样的。允许您将负载拆分为更多请求的更高级的解决方案正在用于enqueueLinksByClickingElements对下一页进行排队。但我不是 100% 确定它会在这个用例中正常工作。
  2. 它是同一个 Puppeteer 实例,所以没有限制。Apify 取决于puppeteer包。
  3. 唯一的大区别是 Apify 使在 Puppeteer 中使用经过身份验证的代理变得简单,否则,它是相同的。当然,PuppeteerCrawler 为您提供了大量功能,例如自动缩放并发、重试、代理轮换、会话等。

推荐阅读