【问题标题】:Webscraping paginated website with different page layout using Puppeteer使用 Puppeteer 抓取具有不同页面布局的 Web Scraping 分页网站
【发布时间】:2019-03-04 04:47:31
【问题描述】:

我正在尝试对本网站上的 200 多个页面进行分页,但并非所有页面都具有相同的布局。例如:这些学校的 GPA 细分和 SAT/ACT(在测试政策行中)超级分数不同。而对于哈佛大学的页面,SAT/ACT 超级分数完全没有出现。我在尝试将其格式化为 csv 时遇到问题,因为这些数据显示在一页但不显示其他页面。

链接: https://www.princetonreview.com/college/georgia-institute-technology-1022905 https://www.princetonreview.com/college/princeton-university-1024041 https://www.princetonreview.com/college/harvard-college-1022984

我目前拥有的 CSV 文件:https://ibb.co/Tc3DyFR 此示例仅显示超级分数的差异,因为我还没有抓取 GPA 细分。但是,这两种布局在不同的页面上是不同的。

代码:

const puppeteer = require('puppeteer');
const fs = require('fs-extra');

(async function main() {
try{
    var names = await (fs.readFileSync('names.csv', 'utf8')).split('\n');

    const browser = await puppeteer.launch({ headless: false });
    const page = await browser.newPage();
    page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36');

    await page.goto('https://www.princetonreview.com/college/harvard-college-1022984#!admissions');
    //await fs.writeFile('out.csv', 'School Name,Applicants,Acceptance Rate,Average HS GPA,GPA: Over 3.75,GPA: 3.50-3.74,GPA: 3.25 - 3.49,GPA: 3.00 - 3.24,GPA: 2.50 - 2.99,GPA: 2.00 - 2.49,SAT Reading and Writing,SAT Math,ACT\n');

    await fs.appendFile('out.csv', `"${names[1]}",`);
    const numbers = await page.evaluate(() => {
        let nums = document.querySelectorAll('.number-callout');

        let arr = Array.prototype.slice.call(nums);
        let text_arr = [];
        for(let i = 0; i < arr.length; i++){
            if(arr[i].innerText == "")
                continue;
            text_arr.push(arr[i].innerText.trim());
        }
        return text_arr;
    });

    for(var e of numbers){
        await fs.appendFile('out.csv', `"${e}",`);
    }
    await fs.appendFile('out.csv', `\n`);
    //console.log(numbers);
    await browser.close();
}catch(e){
    console.log('our error', e);
}
})();

【问题讨论】:

    标签: javascript node.js web-scraping puppeteer


    【解决方案1】:

    简答:

    每当您通过单独的样式进行分页时,您必须首先停止考虑通用解决方案。

    单独考虑每个块,并尝试逐个获取数据。这样您就可以根据需要对它们进行格式化和拆分。

    长答案:

    这看起来像是一项非常大的任务/任务,需要在一个问题中解决。然而,这里有一些解决这个问题的方法。

    我们的问题是, - 不同页面的格式不同。 - 有些页面有数据,有些没有。 - 我们需要提取8-10个特定数据。

    假设我们要提取 Superscore SAT 分数,该分数在普莱斯顿和乔治亚州提供,但在哈佛页面上不可用。

    我们需要专门搜索它们,或者优化代码以提取所有数据。没有通用的方法可以神奇地知道什么是什么。

    // Let's grab all elements
    [...document.querySelectorAll('div.number-callout')]
    // And search for specific term
    .find(e=>{
      // We can go upper level and find the link element 
      // since it's the only one identifying this data
      const parent = e.parentNode.querySelector('a')
      // if an element is found, we search for the text there
      if(parent) return parent.innerText.includes('Superscore SAT')
    })
    

    这只会返回前两个的结果。

    这也适用于“Superscore ACT”

    您可以映射元素并合并数据,

    const data = {};
    [...document.querySelectorAll('div.number-callout')].map(e=>{
      const parent = e.parentNode.querySelector('a');
        if(parent){
            if(parent.innerText.includes('Superscore ACT')) data["Superscore ACT"] = true;
            if(parent.innerText.includes('Superscore SAT')) data["Superscore SAT"] = true;
        }
    });
    

    结果:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多