我正在尝试分页浏览该网站上的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);
}
})();
答案 0 :(得分:0)
无论何时使用单独的样式进行分页,都必须首先停止考虑一般的解决方案。
分别考虑每个块,然后尝试一一获取数据。这样,您可以根据需要格式化和破坏它们。
这似乎是一个很大的任务/任务,可以在一个问题中解决。但是,这是解决此问题的一些方法。
我们的问题是 -不同页面的格式不同。 -有些页面有数据,有些则没有。 -我们需要提取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')
})
这只会返回前两个结果。 list
这也适用于“ 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;
}
});