总长DR

总长DR

我正在尝试解析 HTML 页面小狗。这是一个命令行 HTML 解析器,它接受通用 HTML 选择器。我知道我可以使用已经安装在我的机器上的 Python,但我想学习如何使用 pup 来练习命令行。

我想要抓取的网站是 https://ucr.fbi.gov/crime-in-the-us/2018/crime-in-the-us-2018/topic-pages/tables/table-1

我创建了一个 html 文件:

curl https://ucr.fbi.gov/crime-in-the-u.s/2018/crime-in-the-u.s.-2018/topic-pages/tables/table-1 > fbi2018.html

如何提取一列数据,例如“人口”?

这是我最初写的命令:

cat fbi2018.html | grep -A1 'cell31 ' | grep -v 'cell31 ' | sed 's/text-align: right;//' | sed 's/<[/]td>//' | sed 's/--//' | sed '/^[[:space:]]*$/d' | sort -nk1,1 

它确实有效,但这是一种丑陋、hacky 的方法,这就是我想使用 pup 的原因。我注意到“人口”列中我需要的所有值都在标签headers="cell 31 .."内的某个位置<td>。例如:

<td id="cell211" class="odd group1 valignmentbottom numbercell" rowspan="1" colspan="1" headers="cell31 cell210">
323,405,935</td>

我想提取其标签中具有此特定标头的所有值<td>,在这个特定示例中,将是323,405,935

然而,pup 中的多个选择器似乎不起作用。到目前为止,我可以选择所有 td 元素:

cat fbi2018.html | pup 'td'

但我不知道如何选择包含特定查询的标头。

编辑: 输出应该是:

272,690,813
281,421,906
285,317,559
287,973,924
290,788,976
293,656,842
296,507,061
299,398,484
301,621,157
304,059,724
307,006,550
309,330,219
311,587,816
313,873,685
316,497,531
318,907,401
320,896,618
323,405,935
325,147,121
327,167,434

答案1

总长DR

如果您想要该表的“人口”下的整列,请使用此选项:

... | pup 'div#table-data-container:nth-of-type(3) td.group1 text{}'

基本用法

pup确实支持多个选择器。例如,如果您想抓取wanted text!!以下内容:

$ cat file.html
<div>
  <table>
    <tr class='class-a'>
       <td id='aaa'> some text </td>
       <td id='bbb'> some other text. </td>
    </tr>
    <tr class='class-b'>
       <td id='aaa'> wanted text!! </td>
       <td id='bbb'> some other text. </td>
    </tr>
  </table>
</div>

$ cat file.html | pup 'div table tr.class-b td#aaa'
<td id="aaa">
 wanted text!!
</td>

然后添加text{}以仅获取文本:

$ cat file.html | pup 'div table tr.class-b td#aaa text{}'
 wanted text!!

所以在你的情况下应该是:

$ cat fbi2018.html | pup 'td#cell211 text{}'

323,405,935

或者更好的是,您不必下载该页面,只需通过管道curl即可pup

url="https://ucr.fbi.gov/crime-in-the-u.s/2018/crime-in-the-u.s.-2018/topic-pages/tables/table-1"
curl -s "$url" | pup 'td#cell211 text{}'

解释

如果您想要整个列中的值,那么您应该知道要抓取的元素的特征。

在本例中,来自给定链接的“人口”列。在页面上,有 2 个表包含在<div id='table-data-container'>...如果您使用... | pup 'div#table-data-container',它也会从第二个表中获取数据。你不想要这样。

桌子

如何pup知道您想要第一张桌子?嗯,还有另一个提示。正如你所看到的,s 很少<div>。你的桌子在第三格。所以你可以使用CSS 的伪类, 在这种情况下div#table-data-container:nth-of-type(3)

然后,该列具有唯一选择器,如下所示td.group1

选择器

将它们全部组合起来,然后通过管道将其删除以grep -v -e '^$'消除空格。

... | pup 'div#table-data-container:nth-of-type(3) td.group1 text{}' | grep -v -e '^$'

你会得到你想要的:

272,690,813
281,421,906
285,317,559
...
327,167,434

答案2

这里有两个问题:
1)解析 HTML 表中的值
2)执行所需的操作(最小值、最大值等)

我不认为你能够用一行字来完成这一任务。我喜欢将 HTML 表转换为 .csv,然后对 CSV 进行操作的想法。您可以使用 AWK,但我会使用 Python 库 Pandas。如果可以避免的话为什么还要写 bash?

我找到了一种使用 bash 将 HTML 表转换为 .csv 的方法这里

使用 AWK 对列进行平均的示例是这里

相关内容