如何使用 Puppeteer 自动抓取特定列的表格行?

问题描述 投票:0回答:1

我正在尝试制作一个个人项目,该项目将使用刮刀从维基百科收集文本和数字数据,随后将所有这些数据移动到数据库,然后比较所有这些收集的值以进行可视化表示。

但是我在选择想要收集的值时遇到了一些困难,特别是对于 HTML 表格。我想选择内部包含数据且仅包含特定列的所有行。

例如我有一个这样的表:

Column1       column2    column3
rowdata1      rowdata1   rowdata1
rowdata2      rowdata2   rowdata2

我想让它看起来像这样:

Column1       column3 
rowdata1      rowdata1   
rowdata2      rowdata2   
例如,没有第二列及其行。那么,有没有什么简单直接的解决方案呢?因为使用 Xpath 手动选择姓名和号码需要很长时间。下面是我当前代码的示例

const puppeteer = require('puppeteer'); async function scrapewiki(url) { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto(url); const [el] = await page.$x('/html/body/div[3]/div[3]/div[5]/div[1]/table/tbody/tr[2]/td[1]/a'); const txt = await el.getProperty('textContent'); const country = await txt.jsonValue(); const [el2] = await page.$x('/html/body/div[3]/div[3]/div[5]/div[1]/table/tbody/tr[2]/td[3]'); const txt2 = await el2.getProperty('textContent'); const population = await txt2.jsonValue();
    
javascript web-scraping puppeteer
1个回答
1
投票
首先,请

避免使用浏览器生成的 CSS 选择器和 XPath 。它们有时很方便,但几乎总是次优。查看表格,有一种更简洁的方法来识别您想要的数据:<table class="wikitable sortable">

。该表每行都有 
<tr>
 元素和 
<td>
 单元格。标准表格设置在这里。

CSS 选择器

table.wikitable.sortable tr

(我假设它是页面上唯一的选择器)给出所有行,对于每一行,使用选择器 
td
 提取单元格,给出一个二维表格。 
.slice(2)
 对于撕掉标题很有用。

其次,这是个人观点,但我几乎总是使用 CSS 选择器,除非我

have 使用 XPath 或者这是它们更干净的特殊情况。 XPath 语法比 CSS 选择器更糟糕。

const puppeteer = require("puppeteer"); // 15.4.0 let browser; (async () => { browser = await puppeteer.launch({headless: true}); const [page] = await browser.pages(); const url = "https://en.wikipedia.org/wiki/List_of_countries_and_dependencies_by_population"; await page.goto(url, {waitUntil: "domcontentloaded"}); const tableSel = "table.wikitable.sortable tr"; const data = await page.$$eval(tableSel, els => els.slice(2).map(el => [...el.querySelectorAll("td")] .map(e => e.textContent.trim()) ) ); const nameAndPop = data.map(e => [e[0], e[2]]); console.table(nameAndPop.slice(0, 10)); console.log("total rows", data.length); })() .catch(err => console.error(err)) .finally(() => browser?.close()) ;
最后,

您不需要 Puppeteer 来完成此操作。最好使用 Wikipedia API,或者使用简单的轻量级 HTTP fetch

/
axios
 请求与 Cheerio 等 HTML 解析库结合使用。您可以考虑将上述代码仅用于教育目的;这不是最好的做事方式。

考虑在节点 18 上使用带有

fetch

 的 Cheerio:

const cheerio = require("cheerio"); // 1.0.0-rc.12 fetch("https://en.wikipedia.org/wiki/List_of_countries_and_dependencies_by_population") .then(res => res.text()) .then(text => { const $ = cheerio.load(text); const rows = []; $("table.wikitable.sortable tr").slice(2).each(function (i, e) { const row = []; rows.push(row); $(this).find("td").each(function (i, e) { row.push($(this).text().trim()); }); }); const nameAndPop = rows.map(e => [e[0], e[2]]); console.table(nameAndPop); console.table(rows.length); }) ;
在我的慢速 Windows 10 上网本上,我可以在 3 秒内运行 Cheerio 脚本,而具有冷缓存的 Puppeteer 需要 34 秒(使用 

Measure-Command

)。

禁用 JS 并阻止图像和其他资源对于 Puppeteer 来说是个好主意,但我没有打扰;大部分开销是启动浏览器。

另请参阅:

  • 想要使用 Puppeteer 来抓取表格。如何获取所有行,遍历行,然后获取每行的“td's”?
  • 从二维数组中获取列

披露:我是链接博客文章的作者。

© www.soinside.com 2019 - 2024. All rights reserved.