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
작동하긴 하지만 추악하고 해킹적인 접근 방식이므로 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
그러나 강아지의 여러 선택기가 작동하지 않는 것 같습니다. 지금까지 모든 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를 사용한 열 평균화의 예는 다음과 같습니다.여기