wake-up-neo.net

Können wir xpath mit BeautifulSoup verwenden?

Ich benutze BeautifulSoup, um eine URL zu kratzen, und ich hatte den folgenden Code

import urllib
import urllib2
from BeautifulSoup import BeautifulSoup

url =  "http://www.example.com/servlet/av/ResultTemplate=AVResult.html"
req = urllib2.Request(url)
response = urllib2.urlopen(req)
the_page = response.read()
soup = BeautifulSoup(the_page)
soup.findAll('td',attrs={'class':'empformbody'})

Jetzt können wir im obigen Code findAll verwenden, um Tags und damit verbundene Informationen abzurufen, aber ich möchte xpath verwenden. Ist es möglich, xpath mit BeautifulSoup zu verwenden? Kann mir jemand nach Möglichkeit einen Beispielcode zur Verfügung stellen, damit dieser hilfreicher ist?

Nein, BeautifulSoup selbst unterstützt keine XPath-Ausdrücke.

Eine alternative Bibliothek ( lxml , unterstützt XPath 1.0. Es hat einen BeautifulSoup-kompatiblen Modus , in dem es versucht, kaputtes HTML zu analysieren, wie es Soup tut. Der Standard lxml HTML-Parser ist jedoch genauso gut geeignet, um kaputtes HTML zu analysieren, und ich glaube, er ist schneller.

Nachdem Sie Ihr Dokument in einen XML-Baum geparst haben, können Sie mit der .xpath() -Methode nach Elementen suchen.

import urllib2
from lxml import etree

url =  "http://www.example.com/servlet/av/ResultTemplate=AVResult.html"
response = urllib2.urlopen(url)
htmlparser = etree.HTMLParser()
tree = etree.parse(response, htmlparser)
tree.xpath(xpathselector)

Von möglichem Interesse für Sie ist die CSS Selector-Unterstützung ; Die Klasse CSSSelector übersetzt CSS-Anweisungen in XPath-Ausdrücke, was die Suche nach td.empformbody erheblich vereinfacht:

from lxml.cssselect import CSSSelector

td_empformbody = CSSSelector('td.empformbody')
for elem in td_empformbody(tree):
    # Do something with these table cells.

Der Kreis schließt sich: BeautifulSoup selbst hat eine sehr vollständige CSS-Selektor-Unterstützung :

for cell in soup.select('table#foobar td.empformbody'):
    # Do something with these table cells.
144
Martijn Pieters

Ich kann bestätigen, dass es in Beautiful Soup keine XPath-Unterstützung gibt.

97

Martijns Code funktioniert nicht mehr richtig (er ist mittlerweile 4+ Jahre alt ...). Die Zeile etree.parse() wird in der Konsole gedruckt und weist der Variablen tree keinen Wert zu. Unter Bezugnahme auf this konnte ich herausfinden, dass dies mit Anfragen und lxml funktioniert:

from lxml import html
import requests

page = requests.get('http://econpy.pythonanywhere.com/ex/001.html')
tree = html.fromstring(page.content)
#This will create a list of buyers:
buyers = tree.xpath('//div[@title="buyer-name"]/text()')
#This will create a list of prices
prices = tree.xpath('//span[@class="item-price"]/text()')

print 'Buyers: ', buyers
print 'Prices: ', prices
35
wordsforthewise

BeautifulSoup hat eine Funktion namens findNext vom aktuellen Element gerichtet childern, so:

father.findNext('div',{'class':'class_value'}).findNext('div',{'id':'id_value'}).findAll('a') 

Der obige Code kann den folgenden xpath imitieren:

div[class=class_value]/div[id=id_value]
13
user3820561

Ich habe ihre docs durchsucht und es scheint, dass es keine xpath-Option gibt. Wie Sie sehen können hier bei einer ähnlichen Frage zu SO, bittet das OP um eine Übersetzung von xpath zu BeautifulSoup, daher wäre meine Schlussfolgerung - nein, es ist kein xpath-Parsing verfügbar.

1
Nikola

wenn Sie lxml ganz einfach verwenden:

tree = lxml.html.fromstring(html)
i_need_element = tree.xpath('//a[@class="shared-components"]/@href')

aber wenn Sie BeautifulSoup BS4 verwenden, ist das auch ganz einfach:

  • zuerst "//" und "@" entfernen
  • sekunde - Stern vor "=" hinzufügen

versuche diese Magie:

soup = BeautifulSoup(html, "lxml")
i_need_element = soup.select ('a[class*="shared-components"]')

wie Sie sehen, unterstützt dies kein Sub-Tag, daher entferne ich den Teil "/ @ href"

1

Dies ist ein ziemlich alter Thread, aber es gibt jetzt eine Umgehungslösung, die zu diesem Zeitpunkt möglicherweise noch nicht in BeautifulSoup enthalten war.

Hier ist ein Beispiel von dem, was ich getan habe. Ich verwende das Modul "Anfragen", um einen RSS-Feed zu lesen und dessen Textinhalt in einer Variablen namens "rss_text" abzurufen. Damit starte ich es in BeautifulSoup, suche nach xpath/rss/channel/title und rufe dessen Inhalt ab. Es ist nicht gerade XPath in seiner ganzen Pracht (Platzhalter, mehrere Pfade usw.), aber wenn Sie nur einen grundlegenden Pfad haben, den Sie suchen möchten, funktioniert dies.

from bs4 import BeautifulSoup
rss_obj = BeautifulSoup(rss_text, 'xml')
cls.title = rss_obj.rss.channel.title.get_text()
0
David A