python BeautifulSoup 구문 분석 테이블


89

저는 파이썬 requests과 BeautifulSoup을 배우고 있습니다. 연습을 위해 저는 빠른 NYC 주차 티켓 파서를 작성하기로 선택했습니다. 꽤 추한 html 응답을 얻을 수 있습니다. 내가 잡아해야 할 lineItemsTable모든 티켓을 구문 분석합니다.

여기로 이동 https://paydirect.link2gov.com/NYCParking-Plate/ItemSearch하여 NY플레이트를 입력 하여 페이지를 재현 할 수 있습니다.T630134C

soup = BeautifulSoup(plateRequest.text)
#print(soup.prettify())
#print soup.find_all('tr')

table = soup.find("table", { "class" : "lineItemsTable" })
for row in table.findAll("tr"):
    cells = row.findAll("td")
    print cells

누군가 나를 도울 수 있습니까? 모든 것을 찾는 단순한 tr것은 나를 어디에도 가지지 않습니다.


자세히 읽어 보면 실제로 귀하의 질문이 무엇인지 잘 모르겠습니다. 도움이 필요한 부분을 정확히 설명 할 수 있습니까?
TML 2014

질문 링크가 깨짐 : 일반적인 <테이블>에 대한 작업 예제 를 아래에서 확인하십시오.
eusoubrasileiro

답변:


171

여기 있습니다 :

data = []
table = soup.find('table', attrs={'class':'lineItemsTable'})
table_body = table.find('tbody')

rows = table_body.find_all('tr')
for row in rows:
    cols = row.find_all('td')
    cols = [ele.text.strip() for ele in cols]
    data.append([ele for ele in cols if ele]) # Get rid of empty values

이것은 당신에게 제공합니다 :

[ [u'1359711259', u'SRF', u'08/05/2013', u'5310 4 AVE', u'K', u'19', u'125.00', u'$'], 
  [u'7086775850', u'PAS', u'12/14/2013', u'3908 6th Ave', u'K', u'40', u'125.00', u'$'], 
  [u'7355010165', u'OMT', u'12/14/2013', u'3908 6th Ave', u'K', u'40', u'145.00', u'$'], 
  [u'4002488755', u'OMT', u'02/12/2014', u'NB 1ST AVE @ E 23RD ST', u'5', u'115.00', u'$'], 
  [u'7913806837', u'OMT', u'03/03/2014', u'5015 4th Ave', u'K', u'46', u'115.00', u'$'], 
  [u'5080015366', u'OMT', u'03/10/2014', u'EB 65TH ST @ 16TH AV E', u'7', u'50.00', u'$'], 
  [u'7208770670', u'OMT', u'04/08/2014', u'333 15th St', u'K', u'70', u'65.00', u'$'], 
  [u'$0.00\n\n\nPayment Amount:']
]

몇 가지 참고할 사항 :

  • 위 출력의 마지막 행인 지불 금액은 테이블의 일부가 아니라 테이블이 배치되는 방식입니다. 목록의 길이가 7 미만인지 확인하여 필터링 할 수 있습니다.
  • 모든 행의 마지막 열은 입력 텍스트 상자이므로 별도로 처리해야합니다.

5
왜 그것이 당신을 위해 작동하는지 궁금합니다 ... 나는rows = table_body.find_all('tr') AttributeError: 'NoneType' object has no attribute 'find_all'
Cmag

@Cmag Beautiful Soup 4를 사용하고 계십니까?
shaktimaan 2014

1
교체 find_allfindAll
user2314737

3
@ user2314737 BS는 카멜 케이스와 밑줄 표기법을 모두 지원합니다. 저는 파이썬 코딩 지침과 일치하는 밑줄을 사용합니다.
shaktimaan

2
Ok 나는 내 오류를 해결 table = soup.find('table', attrs={'class':'analysis'})했습니다. 그래서 나에 따르면 오류 AttributeError: 'NoneType' object has no attribute 'find_all'가 발생하는 원인은 페이지의 html에없는 태그 나 필드를 전달할 때입니다.
Umesh Kaushik

23

해결되었습니다. 다음은 html 결과를 구문 분석하는 방법입니다.

table = soup.find("table", { "class" : "lineItemsTable" })
for row in table.findAll("tr"):
    cells = row.findAll("td")
    if len(cells) == 9:
        summons = cells[1].find(text=True)
        plateType = cells[2].find(text=True)
        vDate = cells[3].find(text=True)
        location = cells[4].find(text=True)
        borough = cells[5].find(text=True)
        vCode = cells[6].find(text=True)
        amount = cells[7].find(text=True)
        print amount

14

업데이트 : 2020

프로그래머가 웹 페이지의 테이블 구문 분석에만 관심이있는 경우 pandas 메서드를 사용할 수 있습니다 pandas.read_html.

https://worldpopulationreview.com/countries/countries-by-gdp/#worldCountries 웹 사이트에서 GDP 데이터 테이블을 추출한다고 가정 해 보겠습니다.

그런 다음 다음 코드가 작업을 완벽하게 수행합니다 (beautifulsoup 및 멋진 html 필요 없음).

import pandas as pd
import requests

url = "https://worldpopulationreview.com/countries/countries-by-gdp/#worldCountries"

r = requests.get(url)
df_list = pd.read_html(r.text) # this parses all the tables in webpages to a list
df = df_list[0]
df.head()

산출

웹 사이트에서 표의 처음 5 줄


동의합니다. 이것이 2020 년 현재 최선의 접근 방식입니다!
kfmfe04

1
프로젝트 어딘가에서 이미 팬더를 사용하는 경우에만. 한 테이블에 너무 많은 종속성
Сергей Яхницкий

3

다음은 일반 <table>. ( 질문 링크가 깨짐 )

여기 국가에서 GDP (국내 총생산)별로 표를 추출합니다 .

htmltable = soup.find('table', { 'class' : 'table table-striped' })
# where the dictionary specify unique attributes for the 'table' tag

tableDataText함수는 <table> 여러 태그 <tr>(테이블 행)와 내부 <td>(테이블 데이터) 태그가 뒤 따르는 태그로 시작된 html 세그먼트를 구문 분석 합니다. 내부 열이있는 행 목록을 반환합니다. <th>첫 번째 행에서 하나 (테이블 헤더 / 데이터) 만 허용합니다 .

def tableDataText(table):       
    rows = []
    trs = table.find_all('tr')
    headerow = [td.get_text(strip=True) for td in trs[0].find_all('th')] # header row
    if headerow: # if there is a header row include first
        rows.append(headerow)
        trs = trs[1:]
    for tr in trs: # for every table row
        rows.append([td.get_text(strip=True) for td in tr.find_all('td')]) # data row
    return rows

그것을 사용하여 우리는 (처음 두 행)을 얻습니다.

list_table = tableDataText(htmltable)
list_table[:2]

[['Rank',
  'Name',
  "GDP (IMF '19)",
  "GDP (UN '16)",
  'GDP Per Capita',
  '2019 Population'],
 ['1',
  'United States',
  '21.41 trillion',
  '18.62 trillion',
  '$65,064',
  '329,064,917']]

pandas.DataFrame고급 도구를 위해 쉽게 변환 할 수 있습니다 .

import pandas as pd
dftable = pd.DataFrame(list_table[1:], columns=list_table[0])
dftable.head(4)

pandas DataFrame html 테이블 출력

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.