Seite 1 von 1

Mal wieder Website Parsing

Verfasst: Dienstag 1. März 2011, 13:20
von Herr Lehmann
Hallo, ich möchte in einem Script checken ob ein Film in Deutschland oder USA DVD Premiere hatte.

Diese Info bekommt man über IMDB:

z.b. http://www.imdb.com/title/tt0425210/releaseinfo

Der Quelltext sieht auszugsweise so aus:

Code: Alles auswählen

<tr><td><b><a href="/calendar/?region=ES">Spain</a></b></td>
    <td align="right"><a href="/date/04-07/">7 April</a> <a href="/year/2006/">2006</a></td>

    <td></td></tr>

<tr><td><b><a href="/calendar/?region=US">USA</a></b></td>
    <td align="right"><a href="/date/04-07/">7 April</a> <a href="/year/2006/">2006</a></td>
    <td></td></tr>


<tr><td><b><a href="/calendar/?region=DE">Germany</a></b></td>
    <td align="right"><a href="/date/01-11/">11 January</a> <a href="/year/2007/">2007</a></td>

    <td> (DVD premiere)</td></tr>

<tr><td><b><a href="/calendar/?region=JP">Japan</a></b></td>
    <td align="right"><a href="/date/01-13/">13 January</a> <a href="/year/2007/">2007</a></td>
    <td></td></tr>
Bei dem Beispiel wäre es jetzt so, dass der Film in Deutschland DVD Premiere hatte, aber nicht in den USA.
Das möchte ich jetzt automatisch für verschiedene Filme überprüfen lassen.

Mir ist nicht ganz klar wie ich das mit Regex oder BeutifulSoup anstellen sollte, da ich ja nicht z.b. nach <td> (DVD premiere)</td></tr> suchen kann weil das auch bei anderen Ländern stehen könnte. Gutes Beispiel Dafür ist:
http://www.imdb.com/title/tt0403407/releaseinfo

Ich freue mich auf eure Lösungsvorschläge :D

Gruß

Re: Mal wieder Website Parsing

Verfasst: Dienstag 1. März 2011, 13:26
von Leonidas
Es gibt direkt ein ImDB-Modul für Python, wozu parst du die Webseite?

Re: Mal wieder Website Parsing

Verfasst: Dienstag 1. März 2011, 13:29
von Herr Lehmann
Die info bekomme ich nicht mit dem IMDB Modul

Re: Mal wieder Website Parsing

Verfasst: Dienstag 1. März 2011, 13:37
von BlackJack
@Herr Lehmann: Am besten schaut man sich HTML/XML auch immer mal als Baumstruktur an und überlegt, wie man von einem Zweig den man einfach finden kann, zu dem mit der gewünschten Information gelangt. Man kann von einer Fundstelle ja auch einfach wieder im Baum nach oben wandern. Und eine interaktive Python-Shell ist bei so etwas auch immer recht hilfreich um sich dem Ergebnis zu nähern:

Code: Alles auswählen

In [67]: a = soup.find(text=' (DVD premiere)')

In [68]: a
Out[68]: u' (DVD premiere)'

In [69]: a.parent
Out[69]: <td> (DVD premiere)</td>

In [70]: a.parent.parent
Out[70]: 
<tr><td><b><a href="/calendar/?region=DE">Germany</a></b></td>
<td align="right"><a href="/date/01-11/">11 January</a> <a href="/year/2007/">2007</a></td>
<td> (DVD premiere)</td></tr>

In [71]: a.parent.parent.td
Out[71]: <td><b><a href="/calendar/?region=DE">Germany</a></b></td>

In [72]: a.parent.parent.td.find(text=True)
Out[72]: u'Germany'

Re: Mal wieder Website Parsing

Verfasst: Dienstag 1. März 2011, 13:38
von sma
Der HTML-Parser von lxml und XPath-Ausdrücke wären mein Lösungsansatz.

Stefan

Re: Mal wieder Website Parsing

Verfasst: Dienstag 1. März 2011, 15:11
von BlackJack
Eine Übersetzung in XPath:

Code: Alles auswählen

In [118]: doc.xpath('//td[text()=" (DVD premiere)"]/../td[1]//text()')
Out[118]: ['Germany']

Re: Mal wieder Website Parsing

Verfasst: Mittwoch 2. März 2011, 16:53
von Herr Lehmann
danke für die vielen tipps ich schaue mal ob ich damit zurechtkomme

Re: Mal wieder Website Parsing

Verfasst: Dienstag 10. Mai 2011, 09:10
von Herr Lehmann
Ich bin gerade dabei mein Script zu erweitern,

dabei Stoß ich auf folgendes Problem:

Ich nutze die xpath Variante von Blackjack also z.b.
doc.xpath('//td[text()=" (DVD premiere)"]/../td[1]//text()')

jetzt möchte ich aber genau die Länder herausfinden wo KEINE Zusatzinfos in Klammern stehen.

Geht das überhaupt mit Xpath?

Nochmal auszugsweise der Quelltext:

Code: Alles auswählen

<tr><td><b><a href="/calendar/?region=ES">Spain</a></b></td>
    <td align="right"><a href="/date/04-07/">7 April</a> <a href="/year/2006/">2006</a></td>

    <td></td></tr>

<tr><td><b><a href="/calendar/?region=US">USA</a></b></td>
    <td align="right"><a href="/date/04-07/">7 April</a> <a href="/year/2006/">2006</a></td>
    <td></td></tr>


<tr><td><b><a href="/calendar/?region=DE">Germany</a></b></td>
    <td align="right"><a href="/date/01-11/">11 January</a> <a href="/year/2007/">2007</a></td>

    <td> (DVD premiere)</td></tr>

<tr><td><b><a href="/calendar/?region=JP">Japan</a></b></td>
    <td align="right"><a href="/date/01-13/">13 January</a> <a href="/year/2007/">2007</a></td>
    <td></td></tr>

Es geht also um die leeren <td></td>.

Jemand eine Idee?

Gruß

Herr Lehmann

P.S. Wenn man alte Beiträge hier nicht recyceln sollte, bitte den Beitrag in ein neues Thema splitten

Re: Mal wieder Website Parsing

Verfasst: Dienstag 10. Mai 2011, 09:34
von BlackJack
Herr Lehmann: Das offensichtliche -- ``doc.xpath('//td[text()=""]/../td[1]//text()')`` -- hast Du schon probiert!?

Re: Mal wieder Website Parsing

Verfasst: Dienstag 10. Mai 2011, 09:55
von Herr Lehmann
Ja, habe ich probiert. Da bekomme ich nie ein Ergebnis.

Re: Mal wieder Website Parsing

Verfasst: Dienstag 10. Mai 2011, 10:41
von BlackJack
@Herr Lehmann: Ich hatte nicht bedacht, dass Textknoten immer einen Inhalt haben müssen. :oops: Also muss man auf ``td``-Elemente testen die keinen Textknoten als Kind haben (getestet mit http://www.imdb.com/title/tt0403407/releaseinfo):

Code: Alles auswählen

In [304]: doc.xpath('//td[not(text())]/../td[1]//text()')
Out[304]: 
['France',
 'Netherlands',
 'Netherlands',
 'Canada',
 'USA',
 'USA',
 'Germany',
 'New Zealand',
 'Germany',
 'Japan',
 'New Zealand',
 'UK',
 'Russia',
 'Argentina',
 'Finland',
 'Spain',
 'Philippines',
 'Hungary',
 'Italy']
Das ist aber wesentlich zerbrechlicher als nach dem doch recht spezifischen Text ' (DVD premiere)' zu suchen. Soll heissen hier würde die Gefahr für falsche Treffer deutlich steigen.

Wenn Du mehrere Informationen aus dieser Tabelle benötigst, wäre es wohl sauberer erst die Tabelle komplett in eine Datenstruktur zu überführen, auf die Du dann die Abfragen machen kannst.

Re: Mal wieder Website Parsing

Verfasst: Dienstag 10. Mai 2011, 13:02
von Herr Lehmann
Deine Lösung bringt leider nicht das gewünschte ergebnis. Es werden dabei einfach nur alle Länder ausgegeben in denen der Film erschienen ist.

Das Resultat müsste sein:

Germany
Russia
Spain
Philippines
Italy

Re: Mal wieder Website Parsing

Verfasst: Dienstag 10. Mai 2011, 13:25
von BlackJack
@Herr Lehmann: Heute ist wohl nicht mein Tag. :oops: So geht's:

Code: Alles auswählen

In [305]: doc.xpath('//td[not(node())]/../td[1]//text()')
Out[305]: ['Germany', 'Russia', 'Spain', 'Philippines', 'Italy']

Re: Mal wieder Website Parsing

Verfasst: Dienstag 10. Mai 2011, 13:35
von Hyperion
Ein Test mittels `string-length()` scheint zu klappen:

Code: Alles auswählen

In [10]: root.xpath('//td[not(string-length())]/../td[1]//text()')
Out[10]: ['Germany', 'Russia', 'Spain', 'Philippines', 'Italy']

Re: Mal wieder Website Parsing

Verfasst: Dienstag 10. Mai 2011, 14:04
von Herr Lehmann
Ich danke euch! Habt ihr vl eine gute Referenz zu XPath? Ich finde da leider immer noch sehr lückenhafte Docus wie z.b.

http://lxml.de/xpathxslt.html

Aber jetzt komm ich erstmal weiter.

Re: Mal wieder Website Parsing

Verfasst: Dienstag 10. Mai 2011, 14:15
von EyDu
Sehr genau kannst du es hier nachlesen.