2013-06-15 20 views
5

Ich habe folgende Text von meinem Code in Python verarbeitet:Extrahieren von Daten aus HTML mit 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> 

Können Sie mir raten, wie die Daten zu extrahieren, aus <td>? Meine Idee ist, es in eine CSV-Datei mit dem folgenden Format zu setzen: some link, some data 1, some data 2, some data 3.

Ich erwarte, dass ohne regulären Ausdruck es schwer sein könnte, aber wirklich habe ich immer noch gegen reguläre Ausdrücke kämpfen.

benutzen ich meinen Code mehr oder weniger in folgenden Weise:

tabulka = subpage.find("table") 

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

und idealerweise jeden td in einigen Array behaupten wäre zu bekommen. Html oben ist ein Ergebnis von Python.

+0

Sie können Beautifouloup http://www.crummy.com/software/BeautifulSoup/bs3/documentation.html verwenden, um die Informationen zu extrahieren, anstatt dann regulären Ausdruck zu verwenden. – locojay

+0

Verwenden Sie keine regulären Ausdrücke, um nicht-triviales HTML zu analysieren. – Cairnarvon

+0

Ich kann BeautifulSoup verwenden, um Daten aus td zu extrahieren, aber was soll ich als nächstes tun, um an Daten zu arbeiten? – Lormitto

Antwort

10

Get BeautifulSoup und einfach verwenden. Es ist großartig.

$> 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() gibt eine Liste oder None zurück und Listen und None haben keine .text() -Methode, daher ist Ihre letzte Zeile immer ein Fehler. – 7stud

+0

wie 7stud oben angegeben ist es ein Problem in der Tat – Lormitto

4

Sie sollten Regexes nicht auf HTML verwenden. Sie sollten BeautifulSoup oder lxml verwenden. Hier sind einige Beispiele mit BeautifulSoup:

Ihre td-Tags tatsächlich aussehen wie folgt aus:

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

So td.text wie folgt aussieht:

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

Sie können sehen, dass jede Saite getrennt durch mindestens eine neue Zeile, so dass Sie jede Zeichenfolge trennen können.

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 

Oder prägnanter:

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

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

Aber diese Lösung ist spröde, weil es nicht funktioniert, wenn Ihre HTML wie folgt aussieht:

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

Jetzt td.text sieht wie folgt aus :

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

Und dort ist kein Weg herauszufinden, wo einige der Strings beginnen und enden. Aber das nur bedeutet, dass Sie nicht td.text verwenden - es gibt noch andere Möglichkeiten, jede Zeichenfolge zu identifizieren:

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 
Verwandte Themen