我正在尝试进行网页抓取,而我手把手放在一个看起来很容易抓取的网站上。但是,该网站具有许多具有相同ID的元素,这使得使用选择器变得很困难。
因此,我试图使用其完整的XPath获取元素。问题是,当我在网站上打开Chrome控制台并输入:
$x("/html/body/div[2]/div[4]/div/table[2]/tbody/tr/td[1]/div[1]/div[1]/table/tbody/tr[1]/td/table/tbody/tr[2]/td[2]")
有时可以,有时不能。我注意到它特别在检查元素之后起作用。我在其他线程上发现它可能与iframe有关,但是chrome控制台的iframe选择在它起作用或不起作用时似乎没有改变。
使用Puppeteer,此表达式始终返回一个空元素。这是我的代码的一部分:
const puppeteer = require('puppeteer');
const URL = "https://www.soccerstats.com/results.asp?league=england_2019&pmtype=bygameweek";
let browser = await puppeteer.launch(properties);
let page = await browser.newPage();
await page.goto(URL, {timeout: 60000, waitUntil: 'domcontentloaded'}).then(() => {
console.log('success')
});
let match_xpath = "/html/body/div[2]/div[4]/div/table[2]/tbody/tr/td[1]/div[1]/div[1]/table/tbody/tr[1]/td/table/tbody/tr[2]/td[2]";
await page.waitForXPath(match_xpath);
let match = (await page.$x(match_xpath))[0];
let info = await page.evaluate((el) => {
return el.innerHTML
}, match);
console.log(info) //This always returns 'undefined'
为什么会这样?如何获取元素的实际内容?
谢谢!
答案 0 :(得分:1)
我认为您在操纵up脚本中的代码不会等待元素显示在浏览器(DOM)中。
因此,您可以设置waitUntil: 'networkidle0'
以等待XHR(AJAX)请求完成并显示在浏览器中。
下面的这段代码仅刮取第一个表
const puppeteer = require('puppeteer')
const URL = 'https://www.soccerstats.com/results.asp?league=england_2019&pmtype=bygameweek'
;(async () => {
const browser = await puppeteer.launch({
headless : true,
devtools : false
})
const [page] = await browser.pages()
page.setDefaultNavigationTimeout(0)
page.setRequestInterception(true)
page.on('request', request => {
if ( request.resourceType() === 'image' ) {
request.abort()
} else {
request.continue()
}
})
await page.goto(URL, {timeout: 0, waitUntil: 'networkidle0'})
const teams = await page.evaluate( () => {
const teams = []
document.querySelectorAll('.tabbertab:not(.tabbertabhide):not(.tabbertabdefault) #btable > tbody > tr:not(.even) > td:not([align])').forEach(item => teams.push(item.innerText.trim()) )
return teams
})
console.log (teams)
await browser.close ()
})()
如果您想让每个#btable
内部的所有团队都可以使用此代码。
PS:我不使用xPath,因为它使用起来不容易,而且容易出错。
const puppeteer = require('puppeteer')
const URL = 'https://www.soccerstats.com/results.asp?league=england_2019&pmtype=bygameweek'
;(async () => {
const browser = await puppeteer.launch({
headless : true,
devtools : false
})
const [page] = await browser.pages()
page.setDefaultNavigationTimeout(0)
page.setRequestInterception(true)
page.on('request', request => {
if ( request.resourceType() === 'image' ) {
request.abort()
} else {
request.continue()
}
})
await page.goto(URL, {timeout: 0, waitUntil: 'networkidle0'})
const allRoundTeams = await page.evaluate( () => {
var allRoundTeams = []
document.querySelectorAll('#btable').forEach(item => {
if (item.querySelector('tbody > tr > td > b') !== null) {
var title = item.querySelector('tbody > tr > td > b').innerText.trim().replace(/(\r\n|\n|\r)/gm,"");
var teams = []
item.querySelectorAll('tbody > tr:not(.even) > td:not([align])').forEach(team => {
teams.push(team.innerText.trim())
})
allRoundTeams.push({
title : title,
teams : teams
})
}
})
return allRoundTeams
})
allRoundTeams.forEach(round => {
console.log(round.title)
console.log('========')
round.teams.forEach(team => {
console.log (team)
})
console.log('\n')
})
await browser.close ()
})()
答案 1 :(得分:0)
尝试将xpath表达式与您的代码一起使用;它应返回第1轮的日期,球队名称和得分,例如:
//div[2]//table[2]//td[1]/div[1]/div[1]/table[1]/tr[1]/td[1]