Webscraping нумерованный веб-сайт с другой версткой с помощью Puppeteer - PullRequest
0 голосов
/ 04 марта 2019

Я пытаюсь разбить на страницы более 200 страниц на этом сайте, и не все из них имеют одинаковый макет.Например: разбивка по GPA и SAT / ACT (в строке политики тестирования) Super Scores в этих школах различны.А на странице Гарвардского колледжа просто не видно SAT / ACT Super Scores.У меня возникают проблемы при попытке отформатировать это для 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 В этом примере показана разница только в Super Scoresпотому что я еще не пересмотрел разбивку ГПД.Однако оба макета отличаются на разных страницах.

Код:

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

1 Ответ

0 голосов
/ 05 марта 2019

Краткий ответ:

Всякий раз, когда вы разбиваете на страницы с помощью отдельного стиля, сначала вы должны перестать думать об общем решении.

Подумайте о каждом блоке отдельно и попытайтесь получить данные по одному.одним.Таким образом, вы можете форматировать и разбивать их по своему усмотрению.

Длинный ответ:

Это похоже на довольно большое задание / задачу, которую нужно решить в одном вопросе.Однако здесь есть некоторые причины для решения этой проблемы.

Наша проблема в том, что - Формат отличается на разных страницах.- На некоторых страницах есть данные, на некоторых нет.- Нам нужно извлечь 8-10 конкретных данных.

Допустим, мы хотим извлечь оценку Superscore SAT , которая доступна на Priceton и Georgia, но не на странице Гарварда.

Нам нужно искать их всех специально или оптимизировать код для извлечения всех данных.Не существует обобщенного способа магического знания, что к чему.

// 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')
})

Это вернет результат только в первых двух.enter image description here

Это также работает с "Superscore ACT"

enter image description here

Вы можете отобразить через элементыи объединить данные,

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

Результат: enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...