pouvons-nous utiliser xpath avec BeautifulSoup?
j'utilise BeautifulSoup pour gratter une url et j'avais le code suivant
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'})
maintenant dans le code ci-dessus nous pouvons utiliser findAll
pour obtenir des tags et des informations les concernant, mais je veux utiliser xpath. Est-il possible d'utiliser XPath avec BeautifulSoup? Si possible, est-ce que quelqu'un peut me fournir un exemple de code pour qu'il soit plus utile?
7 réponses
Non, BeautifulSoup, à lui seul, ne supporte pas les expressions XPath.
Une bibliothèque alternative, lxml , ne support de XPath 1.0. Il a un BeautifulSoup mode compatible où il essaiera et analyse HTML cassé la façon dont la soupe fait. Cependant ,le par défaut lxml HTML parser fait tout aussi bien un travail de parsing HTML cassé, et je crois est plus rapide.
une fois que vous avez analysé votre document dans un arbre lxml, vous pouvez utiliser la méthode .xpath()
pour rechercher des éléments.
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)
d'intérêt possible pour vous est le CSS Selector support ; la classe CSSSelector
traduit les déclarations CSS en expressions XPath, rendant votre recherche pour td.empformbody
beaucoup plus facile:
from lxml.cssselect import CSSSelector
td_empformbody = CSSSelector('td.empformbody')
for elem in td_empformbody(tree):
# Do something with these table cells.
boucler la boucle: BeautifulSoup lui-même ne avoir assez décent CSS selector support :
for cell in soup.select('table#foobar td.empformbody'):
# Do something with these table cells.
je peux confirmer qu'il n'y a pas de support XPath dans la belle soupe.
le code de Martijn ne fonctionne plus correctement (il a maintenant plus de 4 ans...), la ligne etree.parse()
imprime sur la console et n'attribue pas la valeur à la variable tree
. En me référant à ce , j'ai pu comprendre ce travail en utilisant requests et lxml:
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
BeautifulSoup a une fonction appelée findNext de l'élément actuel dirigé childern, so:
father.findNext('div',{'class':'class_value'}).findNext('div',{'id':'id_value'}).findAll('a')
code ci-dessus peut imiter le xpath suivant:
div[class=class_value]/div[id=id_value]
j'ai cherché dans leur docs et il semble qu'il n'y ait pas d'option xpath. En outre, comme vous pouvez voir ici sur une question similaire sur SO, L'OP demande une traduction de xpath à BeautifulSoup, donc ma conclusion serait - non, il n'y a pas de parsing xpath disponible.
c'est un très vieux fil, mais il y a une solution de rechange maintenant, qui n'a peut-être pas été dans BeautifulSoup à l'époque.
Voici un exemple de ce que j'ai fait. J'utilise le module " requêtes "pour lire un flux RSS et obtenir son contenu texte dans une variable appelée"rss_text". Avec cela, je l'exécute par BeautifulSoup, je cherche le XPath/rss/channel / title, et je récupère son contenu. Ce N'est pas exactement XPath dans toute sa gloire (jokers, chemins multiples, etc.), mais si vous avez juste un chemin de base que vous voulez localiser, cela fonctionne.
from bs4 import BeautifulSoup
rss_obj = BeautifulSoup(rss_text, 'xml')
cls.title = rss_obj.rss.channel.title.get_text()
quand vous utilisez lxml tout simple:
tree = lxml.html.fromstring(html)
i_need_element = tree.xpath('//a[@class="shared-components"]/@href')
mais quand utiliser BeautifulSoup BS4 tout simple aussi:
- d'abord enlever les "//" et "@"
- deuxième-ajouter l'étoile avant " = "
essayez cette magie:
soup = BeautifulSoup(html, "lxml")
i_need_element = soup.select ('a[class*="shared-components"]')
comme vous le voyez, cela ne supporte pas les sous-tags, donc je supprime" / @href "part