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
それは実際には機能しますが、醜く、ハックな方法なので、子犬を使いたいのです。 「Population」列から必要なすべての値に、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
になります。
しかし、子犬の複数のセレクターは機能しないようです。これまでのところ、すべてのtd要素を選択できます。
cat fbi2018.html | pup 'td'
しかし、特定のクエリを含むヘッダーを選択する方法がわかりません。
EDIT:出力は次のようになります。
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
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{}'
_
そのテーブルの「母集団」の下に列全体が必要な場合は、これを使用します。
_... | pup 'div#table-data-container:nth-of-type(3) td.group1 text{}'
_
列全体の値が必要な場合は、スクレイピングする要素の特性を知っている必要があります。
この場合、特定のリンクからの「人口」列。このページには、2つのテーブルが_<div id='table-data-container'>...
_でラップされています。_... | pup 'div#table-data-container'
_を使用すると、2番目のテーブルからデータも取得されます。あなたはそれを望まない。
どのようにしてpup
は最初のテーブルが必要かを知っていますか?さて、別のヒントがあります。ご覧のとおり、_<div>
_ sはほとんどありません。そして、あなたのテーブルは3番目の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
_