Schwierigkeiten mit etree

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Hi!

Als Alternative zu BeautifulSoup habe ich gerade begonnen, eTree auszuprobieren und stoße dabei auf folgendes Problem:

Code: Alles auswählen

>>> from html5lib import HTMLParser
>>> from html5lib.treebuilders import getTreeBuilder
>>> from xml.etree import cElementTree
>>> from __future__ import with_statement
>>> from contextlib import closing
>>> from urllib import urlopen
>>> with closing(urlopen('http://www.python-forum.de')) as f:
	content = f.read()

>>> parser = HTMLParser(tree=getTreeBuilder('etree', cElementTree))
>>> doc = parser.parse(content)
>>> print doc.find('.//span[@class="maintitle"]').text

Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    print doc.find('.//span[@class="maintitle"]').text
  File "C:\Python25\lib\xml\etree\ElementPath.py", line 186, in find
    return _compile(path).find(element)
  File "C:\Python25\lib\xml\etree\ElementPath.py", line 176, in _compile
    p = Path(path)
  File "C:\Python25\lib\xml\etree\ElementPath.py", line 93, in __init__
    "expected path separator (%s)" % (op or tag)
SyntaxError: expected path separator ([)
Laut http://effbot.org/zone/element-xpath.htm müsste das doch funktionieren. Was habe ich also falsch verstanden?

Gruß

Sebastian
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Oh, help(etree) sagt ich habe Version 1.0.6 und das geht laut der Seite erst ab 1.3 :(
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Das ElementTree in der Stdlib von Python 2.5 ist ElementTree 1.2.6.

Ich habe aufgehört mich zu ärgern und bin auf lxml umgestiegen, das hat vollständige XPath-Unterstützung.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Mann, ist das ein Akt hier...

Ich habe jetzt versucht lxml zu installieren:

Code: Alles auswählen

C:\Dokumente und Einstellungen\Sebastian\Eigene Dateien\lxml-2.1.2>setup.py install
Building lxml version 2.1.2.
NOTE: Trying to build without Cython, pre-generated 'src/lxml/lxml.etree.c' needs to be available.
ERROR: Der Befehl "xslt-config" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.

** make sure the development packages of libxml2 and libxslt are installed **

Using build configuration of libxslt
running install
running bdist_egg
running egg_info
writing src\lxml.egg-info\PKG-INFO
writing top-level names to src\lxml.egg-info\top_level.txt
writing dependency_links to src\lxml.egg-info\dependency_links.txt
reading manifest file 'src\lxml.egg-info\SOURCES.txt'
reading manifest template 'MANIFEST.in'
warning: no files found matching 'lxml.etree.c' under directory 'src\lxml'
warning: no files found matching 'lxml.objectify.c' under directory 'src\lxml'
warning: no files found matching 'lxml.etree.h' under directory 'src\lxml'
warning: no files found matching 'lxml.etree_api.h' under directory 'src\lxml'
warning: no files found matching 'etree_defs.h' under directory 'src\lxml'
warning: no files found matching 'pubkey.asc' under directory 'doc'
warning: no files found matching 'tagpython*.png' under directory 'doc'
writing manifest file 'src\lxml.egg-info\SOURCES.txt'
installing library code to build\bdist.win32\egg
running install_lib
running build_py
running build_ext
error: Python was built with Visual Studio 2003;
extensions must be built with a compiler than can generate compatible binaries.
Visual Studio 2003 was not found on this system. If you have Cygwin installed,
you can try compiling with MingW32, by passing "-c mingw32" to setup.py.
Ich habe dann beim Versuch, Visual Studio 2003 zu installieren, auch wieder eine Fehlermeldung erhalten. :(

Jemand nen Tipp, was zu tun ist?
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Leonidas hat geschrieben:Ich habe aufgehört mich zu ärgern und bin auf lxml umgestiegen, das hat vollständige XPath-Unterstützung.
Dann geht bei dir `position()>2`?

Mal davon ab, dass lxml mit "full XPath support" wirbt, aber dabei nicht auf die Version (1.0 oder 2.0) eingeht. Wenn ich das von letzter Woche recht in Erinnerung habe, verriet mir der Blick auf libxml2, dass es sich nur um XPath 1.0 handelt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

snafu hat geschrieben:Jemand nen Tipp, was zu tun ist?
Das vorkompiliere Egg für 2.1.1 zu nehmen. Oder den Installer, was man halt bevorzugt.

Y0Gi, du hast recht, das wird nur insoweit unterstützt wie libxml2 das eben kann. Kann mir aber herzlich egal sein, da fürs navigieren in HTML XPath 1.0 reicht. Wobei ich nicht einmal das nutzen muss. Und was dir aus XPath 2 fehlt, das kannst du dir sicher auch mit Python-Code schreiben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Klar kann ich das, das wird nur leicht umständlicher. Nur wenn das Ding schon XPath (1.0) unterstützt, dann bitte richtig. Wenn `/foo[1]` schon nicht funktioniert, dann hat ist das für mich jenseits von "full XPath support".
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Leonidas hat geschrieben:
snafu hat geschrieben:Jemand nen Tipp, was zu tun ist?
Das vorkompiliere Egg für 2.1.1 zu nehmen. Oder den Installer, was man halt bevorzugt.
Jau, danke. Klappt nun. :)
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Eine Sache verstehe ich noch nicht. Ich habe mir zum Parsen ein kleines Modul geschrieben:

Code: Alles auswählen

from __future__ import with_statement
from contextlib import closing
from urllib import urlopen

from html5lib import HTMLParser
from html5lib.treebuilders import getTreeBuilder
import lxml
from lxml import etree


def parse(url):
    """Parse URL using html5lib and lxml.etree"""
    with closing(urlopen(url)) as f:
        html = f.read()
    parser = HTMLParser(tree=getTreeBuilder('lxml', lxml.etree))
    return parser.parse(html)
Wenn ich es nun im Interpreter nutze, wirft er mir ne Warning:

Code: Alles auswählen

>>> import lxmlparser as parser
>>> doc = parser.parse('http://www.python-forum.de')

Warning (from warnings module):
  File "C:\Python25\lib\site-packages\html5lib-0.11.1-py2.5.egg\html5lib\treebuilders\etree_lxml.py", line 29
    warnings.warn("lxml does not preserve doctype case", DataLossWarning)
DataLossWarning: lxml does not preserve doctype case
Gebe ich den Inhalt der Funktion im Interpreter ein, kommt keine Warning. Ich kann aber anscheinend in beiden Fällen auf den Baum zugreifen, zumindest was den Befehl mit dem Forum hier angeht. Wodurch erklärt sich dieses unterschiedliche Verhalten?
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Das ist mir auch nicht ersichtlich. Der DOCTYPE der Startseite ist ja auch in korrekter Groß-/Kleinschreibung, soweit ich das sehe.

Übrigens ist `http://www.python-forum.de` kein(e) vollständige(r) URL; es fehlt der Slash als Pfadangabe am Ende. Ohne den wird zudem je nach Browser und Webserver ein zusätzlicher Request ausgeführt, der leicht vermeidbar ist.

Übrigens #2: Um lxml unter Ubuntu und Debian zu installieren (kompilieren), brauchte ich neben python-dev die Pakete libxml2 und libxslt1. Und natürlich die Build-Tools selbst.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Y0Gi hat geschrieben:Übrigens #2: Um lxml unter Ubuntu und Debian zu installieren (kompilieren), brauchte ich neben python-dev die Pakete libxml2 und libxslt1. Und natürlich die Build-Tools selbst.
Jau, wenn ich wieder zuhause an meinem Rechner sitze, probiere ich das mal aus. Aber ich denke, die Abhängigkeiten werden ohnehin automatisch aufgelöst (ich vermisse das hier sehr ^^) und kompilieren muss ich ja im Prinzip eh nicht. Es ging mir primär um die Nutzung des Moduls und die habe ich ja jetzt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Y0Gi hat geschrieben:Das ist mir auch nicht ersichtlich. Der DOCTYPE der Startseite ist ja auch in korrekter Groß-/Kleinschreibung, soweit ich das sehe.
Die Warnung sagt ja eher dass die Großschreibung von DOCTYPE selbst nicht von lxml beibehalten wird.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Leonidas: Müsste die Warnung dann nicht bei jeder (HTML parsenden) Gelegenheiten kommen? Das wäre meiner Meinung nach etwas am Sinn bzw. Einsatzzweck einer Warnung vorbei, da eher eine Sache für die Dokumentation. Ich sehe zumindest auch keinen API-Aufruf, der so eine Warnung angemessen erscheinen lassen würde.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Y0Gi hat geschrieben:Leonidas: Müsste die Warnung dann nicht bei jeder (HTML parsenden) Gelegenheiten kommen?
Wenn das HTML einen DOCTYPE besitzt, dann würde ich das annehmen, ja. Das einzige was mich eben da stutzig macht ist, warum aus laut dem OP nicht im interaktiven Interpreter passiert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Leonidas hat geschrieben:Wenn das HTML einen DOCTYPE besitzt, dann würde ich das annehmen, ja. Das einzige was mich eben da stutzig macht ist, warum aus laut dem OP nicht im interaktiven Interpreter passiert.
Musste dich ja nich ma auf den OP verlassen, sondern einfach selber ausprobieren. ;P
Antworten