2010-05-20 23 views
11

Tôi có một tài liệu html và tôi muốn kéo các bảng ra khỏi tài liệu này và trả về chúng dưới dạng mảng. Tôi đang hình dung 2 chức năng, một hàm tìm tất cả các bảng html trong một tài liệu và một hàm thứ hai biến các bảng html thành các mảng 2 chiều.Cách chuyển đổi một bảng HTML thành một mảng trong python

Something như thế này:

htmltables = get_tables(htmldocument) 
for table in htmltables: 
    array=make_array(table) 

Có 2 sản lượng đánh bắt: 1. Các bảng số thay đổi ngày này sang ngày 2. Bảng dưới đây tất cả các loại định dạng thêm kỳ lạ, giống như tag in đậm và chớp, ném một cách ngẫu nhiên in.

Cảm ơn!

Trả lời

1

Pandas có thể trích xuất tất cả các bảng trong html của bạn vào một danh sách các dataframes ngay ra khỏi hộp, giúp bạn tiết kiệm từ việc phân tích các trang bản thân (phát minh lại bánh xe). A DataFrame là loại mảng 2 chiều mạnh mẽ.

Tôi khuyên bạn nên tiếp tục làm việc với dữ liệu qua Pandas vì đây là công cụ tuyệt vời, nhưng bạn cũng có thể chuyển đổi sang các định dạng khác nếu bạn thích (danh sách, từ điển, tệp csv, v.v.).

Ví dụ

"""Extract all tables from an html file, printing and saving each to csv file.""" 

import pandas as pd 

df_list = pd.read_html('my_file.html') 

for i, df in enumerate(df_list): 
    print df 
    df.to_csv('table {}.csv'.format(i)) 

Lấy nội dung html trực tiếp từ web thay vì từ một tập tin sẽ chỉ yêu cầu một sửa đổi nhỏ:

import requests 

html = requests.get('my_url').content 
df_list = pd.read_html(html) 
18

Sử dụng BeautifulSoup (Tôi khuyên bạn nên 3.0.8). Tìm tất cả các bảng là tầm thường:

import BeautifulSoup 

def get_tables(htmldoc): 
    soup = BeautifulSoup.BeautifulSoup(htmldoc) 
    return soup.findAll('table') 

Tuy nhiên, trong Python, một array là 1 chiều và bó buộc phải khá loại tiểu như các mặt hàng (số nguyên, phao, rằng tiểu học). Vì vậy, không có cách nào để siết chặt một bảng HTML trong một Python array.

Có thể bạn có nghĩa là một Python list thay thế? Đó cũng là 1 chiều, nhưng mọi thứ có thể là một mục, vì vậy bạn có thể có danh sách các danh sách (một danh sách phụ cho mỗi thẻ tr, tôi tưởng tượng, có chứa một mục cho mỗi thẻ td).

Điều đó sẽ cung cấp cho:

def makelist(table): 
    result = [] 
    allrows = table.findAll('tr') 
    for row in allrows: 
    result.append([]) 
    allcols = row.findAll('td') 
    for col in allcols: 
     thestrings = [unicode(s) for s in col.findAll(text=True)] 
     thetext = ''.join(thestrings) 
     result[-1].append(thetext) 
    return result 

này có thể chưa được khá gì bạn muốn (không bỏ qua ý kiến ​​HTML, các mặt hàng của các danh sách con là chuỗi unicode và không byte chuỗi, vv) nhưng nó nên dễ điều chỉnh.

+1

đẹp súp là rất tốt và dễ dàng! Ngoài ra, hãy thử sử dụng lxml + xpath nếu tìm thêm tốc độ. –

+0

wow, hoạt động hoàn hảo. Cảm ơn bạn! – Zach

+0

@user, luôn sẵn lòng trợ giúp.Nếu câu trả lời cho câu hỏi của bạn tốt, bạn nên "chấp nhận" câu hỏi đó (bằng cách nhấp vào biểu tượng dấu kiểm bên dưới số phiếu bầu ở góc trên bên trái) - đó là phần quan trọng trong nghi thức của SO! -) –

1

+1 cho người hỏi câu hỏi và người khác với thần Python.
Muốn thử ví dụ này bằng cách sử dụng bộ chọn lxml và CSS.
Có, đây là chủ yếu là giống như ví dụ của Alex:

import lxml.html 
markup = lxml.html.fromstring('''<html><body>\ 
<table width="600"> 
    <tr> 
     <td width="50%">0,0,0</td> 
     <td width="50%">0,0,1</td> 
    </tr> 
    <tr> 
     <td>0,1,0</td> 
     <td>0,1,1</td> 
    </tr> 
</table> 
<table> 
    <tr> 
     <td>1,0,0</td> 
     <td>1,<blink>0,</blink>1</td> 
     <td>1,0,2</td> 
     <td><bold>1</bold>,0,3</td> 
    </tr> 
</table> 
</body></html>''') 

tbl = [] 
rows = markup.cssselect("tr") 
for row in rows: 
    tbl.append(list()) 
    for td in row.cssselect("td"): 
    tbl[-1].append(unicode(td.text_content())) 

pprint(tbl) 
#[[u'0,0,0', u'0,0,1'], 
# [u'0,1,0', u'0,1,1'], 
# [u'1,0,0', u'1,0,1', u'1,0,2', u'1,0,3']] 
+0

Thật lạ khi sử dụng 'list()' thay vì 'plain'. – jfs

+0

@ J.F. vâng, tôi cho là vậy. Cảm ơn cho bình luận, và cho tất cả các câu trả lời tuyệt vời của bạn :-) Giữ cho công việc tốt. – bernie

+0

@ccpizza: điểm tuyệt vời, cảm ơn bạn. Tôi đã cập nhật mã. – bernie

Các vấn đề liên quan