用 pup 解析 HTML
我正在嘗試使用pup解析 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
TLDR
如果您想要該表的“人口”下的整個列,請使用此選項:
... | 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'>...
If you use... | pup 'div#table-data-container'
中,它也會從第二個表中獲取數據。你不想要那個。怎麼
pup
知道你想要第一張桌子?嗯,還有一個提示。如您所見,<div>
s 很少。你的桌子在第三格。所以你可以使用CSS 的 psuedo-classes,在這種情況下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