2013-06-15 18 views
5

ho seguito il testo elaborato dal mio codice in Python:l'estrazione di dati da HTML con Python

<td> 
<a href="http://www.linktosomewhere.net" title="title here">some link</a> 
<br /> 
some data 1<br /> 
some data 2<br /> 
some data 3</td> 

Mi può consigliare come estrarre i dati dal di dentro <td>? La mia idea è di metterlo in un file CSV con il seguente formato: some link, some data 1, some data 2, some data 3.

Mi aspetto che senza un'espressione regolare potrebbe essere difficile ma in realtà sono ancora in lotta con le espressioni regolari.

Ho usato il mio codice più o meno in modo seguente:

tabulka = subpage.find("table") 

for row in tabulka.findAll('tr'): 
    col = row.findAll('td') 
print col[0] 

e idealmente sarebbe quello di ottenere ogni td sostengono in qualche array. Html sopra è un risultato di Python.

+0

È possibile utilizzare Beautifoulsoup http://www.crummy.com/software/BeautifulSoup/bs3/documentation.html per estrarre le informazioni piuttosto che utilizzando un'espressione regolare. – locojay

+0

Non utilizzare espressioni regolari per analizzare il codice HTML non banale. – Cairnarvon

+0

Posso usare BeautifulSoup per estrarre i dati da td ma cosa fare dopo aver lavorato sui dati all'interno? – Lormitto

risposta

10

Ottieni BeautifulSoup e usalo. È ottimo.

$> easy_install pip 
$> pip install BeautifulSoup 
$> python 
>>> from BeautifulSoup import BeautifulSoup as BS 
>>> import urllib2 
>>> html = urllib2.urlopen(your_site_here) 
>>> soup = BS(html) 
>>> elem = soup.findAll('a', {'title': 'title here'}) 
>>> elem[0].text 
+2

findAll() restituisce un elenco o None, e liste e None non hanno un metodo .text(), quindi l'ultima riga è sempre un errore. – 7stud

+0

come 7stud ha dichiarato sopra è davvero un problema – Lormitto

4

Non si dovrebbe utilizzare espressioni regolari in html. Dovresti usare BeautifulSoup o lxml. Ecco alcuni esempi che utilizzano BeautifulSoup:

tuoi tag td in realtà simile a questa:

<td>newline 
<a>some link</a>newline 
<br />newline 
some data 1<br />newline 
some data 2<br />newline 
some data 3</td> 

Così td.text si presenta così:

<newline>some link<newline><newline>some data 1<newline>some data 2<newline>some data 3 

Si può vedere che ogni stringa è separato da almeno una nuova riga, in modo che sia possibile separare ciascuna stringa.

from bs4 import BeautifulSoup as bs 
import re 

html = """<td> 
<a href="http://www.linktosomewhere.net" title="title here">some link</a> 
<br /> 
some data 1<br /> 
some data 2<br /> 
some data 3</td>""" 

soup = bs(html) 
tds = soup.find_all('td') 
csv_data = [] 

for td in tds: 
    inner_text = td.text 
    strings = inner_text.split("\n") 

    csv_data.extend([string for string in strings if string]) 

print(",".join(csv_data)) 

--output:-- 
some link,some data 1,some data 2,some data 3 

O più conciso:

for td in tds: 
    print(re.sub("\n+", ",", td.text.lstrip())) 

--output:-- 
some link,some data 1,some data 2,some data 3 

Ma questa soluzione è fragile, perché non funzionerà se tuo html assomiglia a questo:

<td> 
<a href="http://www.linktosomewhere.net" title="title here">some link</a> 
<br />some data 1<br />some data 2<br />some data 3</td> 

Ora td.text assomiglia a questo :

<newline>some link<newline>some data 1some data2some data3 

E lì non è un modo per capire dove iniziano e finiscono alcune stringhe. Ma questo significa solo che non è possibile utilizzare td.text - ci sono ancora altri modi per identificare ogni stringa:

1)

from bs4 import BeautifulSoup as bs 
import re 

html = """<td> 
<a href="http://www.linktosomewhere.net" title="title here">some link</a> 
<br />some data 1<br />some data 2<br />some data 3</td>""" 

soup = bs(html) 
tds = soup.find_all('td') 
csv_data = [] 

for td in tds: 
    a_tags = td.find_all('a') 

    for a_tag in a_tags: 
     csv_data.append(a_tag.text) 
     br_tags = a_tag.findNextSiblings('br') 

     for br in br_tags: 
      csv_data.append(br.next.strip()) #get the element after the <br> tag 

csv_str = ",".join(csv_data) 
print(csv_str) 

--output:-- 
some link,some data 1,some data 2,some data 3 

2)

for td in tds: 
    a_tag = td.find('a') 
    if a_tag: csv_data.append(a_tag.text) 

    for string in a_tag.findNextSiblings(text=True): #find only text nodes 
     string = string.strip() 
     if string: csv_data.append(string) 

csv_str = ",".join(csv_data) 
print(csv_str) 

--output:-- 
some link,some data 1,some data 2,some data 3 

3)

for td in tds: 
    a_tag = td.find('a') 
    if a_tag: csv_data.append(a_tag.text) 

    text_strings = a_tag.findNextSiblings(text=re.compile('\S+')) #find only non-whitespace text nodes 
    csv_data.extend(text_strings) 

csv_str = ",".join(csv_data) 
print(csv_str) 

--output:-- 
some link,some data 1,some data 2,some data 3