web-dev-qa-db-fra.com

Analyser la table HTML vers Python list?

Je voudrais prendre un tableau HTML et le parcourir pour obtenir une liste de dictionnaires. Chaque élément de la liste serait un dictionnaire correspondant à une ligne du tableau.

Si, par exemple, j'avais un tableau HTML avec trois colonnes (marquées par des balises d'en-tête), "Événement", "Date de début" et "Date de fin" et que ce tableau avait 5 entrées, je voudrais analyser ce tableau pour récupérer une liste de longueur 5 où chaque élément est un dictionnaire avec les clés "Event", "Start Date" et "End Date".

Merci pour l'aide!

43
Andrew

Vous devez utiliser une bibliothèque d'analyse HTML comme lxml :

from lxml import etree
s = """<table>
  <tr><th>Event</th><th>Start Date</th><th>End Date</th></tr>
  <tr><td>a</td><td>b</td><td>c</td></tr>
  <tr><td>d</td><td>e</td><td>f</td></tr>
  <tr><td>g</td><td>h</td><td>i</td></tr>
</table>
"""
table = etree.HTML(s).find("body/table")
rows = iter(table)
headers = [col.text for col in next(rows)]
for row in rows:
    values = [col.text for col in row]
    print dict(Zip(headers, values))

impressions

{'End Date': 'c', 'Start Date': 'b', 'Event': 'a'}
{'End Date': 'f', 'Start Date': 'e', 'Event': 'd'}
{'End Date': 'i', 'Start Date': 'h', 'Event': 'g'}
66
Sven Marnach

De loin, la façon la plus simple d'analyser un tableau HTML est d'utiliser pandas.read_html () - il accepte à la fois les URL et le HTML.

import pandas as pd
url = r'https://en.wikipedia.org/wiki/List_of_S%26P_500_companies'
tables = pd.read_html(url) # Returns list of all tables on page
sp500_table = tables[0] # Select table of interest

Le seul inconvénient est que read_html() ne conserve pas les hyperliens.

29
zelusp

Sven Marnach excellente solution est directement traduisible en ElementTree qui fait partie des distributions récentes Python:

from xml.etree import ElementTree as ET

s = """<table>
  <tr><th>Event</th><th>Start Date</th><th>End Date</th></tr>
  <tr><td>a</td><td>b</td><td>c</td></tr>
  <tr><td>d</td><td>e</td><td>f</td></tr>
  <tr><td>g</td><td>h</td><td>i</td></tr>
</table>
"""

table = ET.XML(s)
rows = iter(table)
headers = [col.text for col in next(rows)]
for row in rows:
    values = [col.text for col in row]
    print dict(Zip(headers, values))

même sortie que la réponse de Sven Marnach ...

28
user688635

Si le HTML n'est pas pas XML, vous ne pouvez pas le faire avec etree. Mais même dans ce cas, vous n'avez pas besoin d'utiliser une bibliothèque externe pour analyser une table HTML. Dans python 3 vous pouvez atteindre votre objectif avec HTMLParser de html.parser. J'ai le code de la classe HTMLParser dérivée simple ici dans un dépôt github .

Vous pouvez utiliser cette classe (nommée ici HTMLTableParser) de la manière suivante:

import urllib.request
from html_table_parser import HTMLTableParser

target = 'http://www.Twitter.com'

# get website content
req = urllib.request.Request(url=target)
f = urllib.request.urlopen(req)
xhtml = f.read().decode('utf-8')

# instantiate the parser and feed it
p = HTMLTableParser()
p.feed(xhtml)
print(p.tables)

La sortie de ceci est une liste de listes 2D représentant des tables. Cela ressemble peut-être à ceci:

[[['   ', ' Anmelden ']],
 [['Land', 'Code', 'Für Kunden von'],
  ['Vereinigte Staaten', '40404', '(beliebig)'],
  ['Kanada', '21212', '(beliebig)'],
  ...
  ['3424486444', 'Vodafone'],
  ['  Zeige SMS-Kurzwahlen für andere Länder ']]]
18
schmijos