Bảng phân tích cú pháp python BeautifulSoup


89

Tôi đang học python requestsvà BeautifulSoup. Đối với một bài tập, tôi đã chọn viết một trình phân tích cú pháp nhanh vé đỗ xe NYC. Tôi có thể nhận được một phản hồi html khá xấu. Tôi cần lấy lineItemsTablevà phân tích tất cả các vé.

Bạn có thể tái tạo trang bằng cách vào đây: https://paydirect.link2gov.com/NYCParking-Plate/ItemSearchvà nhập một NYtấmT630134C

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

Ai đó có thể vui lòng giúp tôi không? Đơn giản là tìm kiếm tất cả trkhông đưa tôi đến đâu.


Khi đọc kỹ hơn, tôi thực sự không chắc câu hỏi của bạn là gì. Bạn có thể làm rõ chính xác phần nào bạn cần giúp đỡ không?
TML

liên kết câu hỏi bị hỏng: Dưới đây là một ví dụ làm việc cho một <bảng> chung.
eusoubrasileiro

Câu trả lời:


172

Của bạn đây:

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

Điều này mang lại cho bạn:

[ [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:']
]

Một số điều cần lưu ý:

  • Hàng cuối cùng trong kết quả ở trên, Số tiền Thanh toán không phải là một phần của bảng nhưng đó là cách bảng được trình bày. Bạn có thể lọc ra bằng cách kiểm tra xem độ dài của danh sách có nhỏ hơn 7 hay không.
  • Cột cuối cùng của mỗi hàng sẽ phải được xử lý riêng biệt vì nó là hộp văn bản đầu vào.

5
Tôi tự hỏi tại sao nó lại hiệu quả với bạn ... Tôi hiểurows = table_body.find_all('tr') AttributeError: 'NoneType' object has no attribute 'find_all'
Sáng

@Cmag Bạn có đang sử dụng Beautiful Soup 4 không?
shaktimaan

1
Thay thế find_allvớifindAll
user2314737

3
@ user2314737 BS hỗ trợ cả trường hợp lạc đà và ký hiệu gạch dưới. Tôi sử dụng gạch dưới phù hợp với các nguyên tắc viết mã Python.
shaktimaan

2
Được rồi, tôi đã giải quyết được lỗi của mình: Trong chế độ xem html, nó hiển thị tbody, tuy nhiên, khi tôi in giá trị của table = soup.find('table', attrs={'class':'analysis'})nó thì không có tbody ở đó, vì vậy chỉ cần tìm td và tr đã thực hiện được công việc. Vì vậy, theo tôi nguyên nhân gây ra lỗi AttributeError: 'NoneType' object has no attribute 'find_all'là khi chúng ta truyền một thẻ hoặc trường không có trong html của trang.
Umesh Kaushik

23

Đã giải quyết, đây là cách bạn phân tích cú pháp kết quả html của họ:

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

15

Cập nhật: 2020

Nếu một lập trình viên chỉ quan tâm đến bảng phân tích cú pháp từ trang web, họ có thể sử dụng phương pháp pandas pandas.read_html.

Giả sử chúng tôi muốn trích xuất bảng dữ liệu GDP từ trang web: https://worldpopulationreview.com/countries/countries-by-gdp/#worldCountries

Sau đó, các mã sau thực hiện công việc một cách hoàn hảo (Không cần đẹp và html cầu kỳ):

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()

Đầu ra

Năm dòng đầu tiên của bảng từ Trang web


Đồng ý - đây rõ ràng là cách tiếp cận tốt nhất tính đến năm 2020!
kfmfe04,

1
Chỉ khi bạn đã sử dụng gấu trúc ở đâu đó trong dự án của mình. Quá nhiều phụ thuộc cho một bảng
Сергей Яхницкий

3

Đây là ví dụ làm việc cho một cái chung <table>. ( liên kết câu hỏi bị hỏng )

Trích xuất bảng từ đây các quốc gia theo GDP (Tổng sản phẩm quốc nội).

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

Các tableDataTextchức năng phân tích một đoạn html bắt đầu với thẻ <table> tiếp theo nhiều <tr>(hàng bảng) và bên trong <td>(bảng dữ liệu) thẻ. Nó trả về một danh sách các hàng với các cột bên trong. Chỉ chấp nhận một <th>(tiêu đề bảng / dữ liệu) trong hàng đầu tiên.

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

Sử dụng nó, chúng tôi nhận được (hai hàng đầu tiên).

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']]

Điều đó có thể được chuyển đổi dễ dàng trong một pandas.DataFramecông cụ nâng cao hơn.

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

pandas DataFrame html xuất bảng

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.