我如何使用puppeteer从谷歌地图上获得所有评论/评论?(因为页面是可滚动的,所以我没有全部得到)



我正试图从我使用Puppeter搜索的地方抓取评论/评论。我有两个问题:

  1. 我从当前页面只得到16条评论/评论,而实际上我想要所有的评论/评论(在这种情况下,62条评论或更多,取决于我的搜索(,但我认为问题来自于页面的可滚动性
  2. 当我在谷歌地图上抓取没有评论的评论时,我遇到了一个错误,上面写着:

    "(node:13184) UnhandledPromiseRejectionWarning: Error: Evaluation failed: TypeError: Cannot read property 'innerText' of null
    at __puppeteer_evaluation_script__:9:38"
    

    ,我不知道每次评论中都有NULL注释时如何消除这种情况(我有一些代码几乎在最后试图解决NULL注释,但不起作用,我尝试了其他一些方法也不起作用(。

下面是我的代码:

const puppeteer = require('puppeteer'); // Require the Package we need...
let scrape = async () => { // Prepare scrape...
const browser = await puppeteer.launch({args: ['--no-sandbox', '--disabled-setuid-sandbox']}); // Prevent non-needed issues for *NIX
const page = await browser.newPage(); // Create request for the new page to obtain...
const busqueda = 'Alitas+del+Cadillac+Tumbaco';
const Url = `https://www.google.com/maps/search/${busqueda}`;
const buscar = '.section-result';
const click1 = '.widget-pane-link';
const cajaTexto = '#searchboxinput';
const comentarioLength = 'section-review-text';
const comentarios = 'div.section-review:nth-child(Index) > div:nth-child(1) > div:nth-child(3) > div:nth-child(2) > div:nth-child(1) > span:nth-child(4)';
console.log(comentarioLength);
//const comentario = 'div.section-review:nth-child(INDEX) > div:nth-child(1) > div:nth-child(3) > div:nth-child(2) > div:nth-child(1) > span:nth-child(4)';
// Replace with your Google Maps URL... Or Test the Microsoft one...
//await page.goto('https://www.google.com/maps/place/Microsoft/@36.1275216,-115.1728651,17z/data=!3m1!5s0x80c8c416a26be787:0x4392ab27a0ae83e0!4m7!3m6!1s0x80c8c4141f4642c5:0x764c3f951cfc6355!8m2!3d36.1275216!4d-115.1706764!9m1!1b1');
await page.goto(Url); // Define the Maps URL to Scrape...
await page.waitFor(2*1000); // In case Server has JS needed to be loaded...
await page.click(buscar); //busco caja de texto*/
await page.waitForNavigation();
await page.waitFor(2*1000);
await page.click(click1);
await page.waitForNavigation();
await page.waitFor(2*1000);
console.log(page.url());
console.log("3");
await page.evaluate(_ => { // This is just a test, don't really need this!
});
await page.waitFor(2*1000);
console.log('how many?', (await page.$$('.section-review-text')).length);
//div.section-result:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(2) > h3:nth-child(1) > span:nth-child(1)
let listLength = await page.evaluate((sel) => {
window.scrollBy(0, window.innerHeight);
return document.getElementsByClassName(sel).length;
}, comentarioLength);
console.log(listLength);
for (let i = 1; i <= listLength; i++) {
let selectorComentarios = comentarios.replace("Index", i);
const result = await page.evaluate((sel) => { // Let's create variables and store values...
return document.querySelector(sel).innerText;
}, selectorComentarios);
if(!result){
continue;
}
console.log(i+result);
}
/*await page.evaluate(_ => {
window.scrollBy(0, window.innerHeight)
})*/
browser.close(); // Close the Browser...
return result; // Return the results with the Review...
};
scrape().then((value) => { // Scrape and output the results...

console.log(value); // Yay, output the Results...
});

要解决第一个问题,您需要通过添加以下函数来处理无限滚动:

async function scrollPage(page, scrollContainer) {
let lastHeight = await page.evaluate(`document.querySelector("${scrollContainer}").scrollHeight`);
while (true) {
await page.evaluate(`document.querySelector("${scrollContainer}").scrollTo(0, document.querySelector("${scrollContainer}").scrollHeight)`);
await page.waitForTimeout(2000);
let newHeight = await page.evaluate(`document.querySelector("${scrollContainer}").scrollHeight`);
if (newHeight === lastHeight) {
break;
}
lastHeight = newHeight;
}
}

在这个函数中,第一个参数是Puppeteerpage,第二个参数是可滚动的HTML元素(在这种情况下,它具有类名.DxyBCb(。此函数检查元素的当前scrollHeight,然后滚动到此高度并再次检查scrollHeight。如果通过加载新元素对其进行了更改,则该功能将再次重复滚动。

这部分代码中的第二个问题:

return document.querySelector(sel).innerText;

您需要处理在页面上找不到具有选择器sel的元素的情况。您可以使用可选的chining,它返回undefined,而不是抛出错误,并在发生错误时添加一些文本:

return document.querySelector(sel)?.innerText || `Element with selector ${sel} not found on the page`;

现在,如果没有搜索选择器,那么求值函数将返回||之后的文本。

博客文章,包含超出您问题范围的更详细信息:使用Nodejs抓取谷歌地图评论。

这违反了谷歌地图平台的服务条款。

请参阅第3.2.4段(对滥用服务的限制(。它读取

(a(无报废。客户不会提取、导出、抓取或缓存谷歌地图内容以供服务之外使用。例如,客户不会:(i(在服务之外预取、索引、存储、重新共享或重新托管谷歌地图内容;(ii(批量下载地理编码;(iii(复制企业名称、地址或用户评论或(iv(将谷歌地图内容与文本到语音服务结合使用。某些服务允许缓存,如地图服务特定条款中所述。

来源:https://cloud.google.com/maps-platform/terms/#3-许可

对不起,我是坏消息的传达者。

最新更新