2010-12-13 72 views
8

J'ai html qui contient des entrées comme ceci:Bibliothèque Python pour l'extraction de texte de type jQuery?

<div class="entry"> 
    <h3 class="foo"> 
    <a href="http://www.example.com/blog-entry-slug" 
    rel="bookmark">Blog Entry</a> 
    </h3> 
    ... 
</div> 

et je voudrais extraire le texte « Blog Entry » (et un certain nombre d'autres attributs, donc je suis à la recherche d'une réponse générique) .

En jQuery, je ne

$('.entry a[rel=bookmark]').text() 

le plus proche, je suis en mesure d'obtenir en Python est:

from BeautifulSoup import BeautifulSoup 
import soupselect as soup 

rawsoup = BeautifulSoup(open('fname.html').read()) 

for entry in rawsoup.findAll('div', 'entry'): 
    print soup.select(entry, 'a[rel=bookmark]')[0].string.strip() 

soupselect de http://code.google.com/p/soupselect/.

Soupselect ne comprend pas la syntaxe complète du sélecteur CSS3, tout comme jQuery. Y a-t-il une telle bête en Python?

Répondre

11

Vous voudrez peut-être jeter un coup d'œil à la classe CSSSelector qui tente d'implémenter des sélecteurs CSS comme décrit dans la spécification w3c. En guise de note, manyfolksrecommend lxml pour analyser HTML/XML sur BeautifulSoup maintenant, pour des raisons de performances et autres.

Je pense que le CSSSelector de lxml utilise XPath pour la sélection des éléments, mais vous pouvez vouloir vérifier la documentation par vous-même. Voici votre exemple avec lxml:

>>> from lxml.cssselect import CSSSelector 
>>> from lxml.html import fromstring 
>>> html = '<div class="entry"><h3 class="foo"><a href="http://www.example.com/blog-entry-slug" rel="bookmark">Blog Entry</a></h3></div>' 
>>> h = fromstring(html) 
>>> sel = CSSSelector("a[rel=bookmark]") 
>>> [e.text for e in sel(h)] 
['Blog Entry'] 
+1

Cela n'a pas fonctionné pour moi pour une raison quelconque (fromstring semble vouloir valide html * lol *), mais l'un des liens que vous avez donné m'a conduit vers pyquery. La motivation pour pyquery était "Hey, faisons jquery en python", et à partir de mes tests préliminaires, j'ai pu compter sur ma connaissance de jQuery au lieu de lire les docs (!) – thebjorn

+2

Utilisez "from lxml.html import fromstring" pour malformé html – Saurav

2

Il est vraiment très facile d'utiliser des arguments de mots-clés.

>>> from BeautifulSoup import BeautifulSoup 
>>> soup = BeautifulSoup('''<div class="entry"> 
... <h3 class="foo"> 
...  <a href="http://www.example.com/blog-entry-slug" 
...  rel="bookmark">Blog Entry</a> 
... </h3> 
... ... 
... </div> 
... ''') 
>>> soup.find('div', 'entry').find(rel='bookmark').text 
u'Blog Entry' 

Alternativement,

>>> for entry in soup('div', 'entry'): 
...  for bookmark in entry(rel='bookmark'): 
...   print bookmark.text 
... 
Blog Entry 

Vous pouvez également utiliser attrs pour effectuer un sélecteur de .entry plutôt que div.entry:

>>> for entry in soup(attrs={'class': 'entry'}): 
...  for bookmark in entry(rel='bookmark'): 
...   print bookmark.text 
... 
Blog Entry 

(note appelant la soupe ou d'une partie de la soupe est équivalent à .findAll().)

Comme une compréhension de la liste, c'est [b.text for e in soup('div', 'entry') for b in e(rel='bookmark')] (produit [u'Blog Entry']).

Si vous voulez de vrais sélecteurs CSS3, je ne connais rien de tel pour BeautifulSoup. Tout (ou presque, presque tout) peut être fait avec une simple imbrication, des conditions et des expressions régulières (vous pouvez également utiliser entry(rel=re.compile('^bookmark$'))). Si vous voulez quelque chose comme ça, considérez-le comme votre prochain projet! Cela pourrait être utile pour aplatir le code et le rendre plus compréhensible pour les internautes.

+0

Cela ne semble pas trop mal. Le problème que j'ai avec BeautifulSoup est que je dois réapprendre l'interface chaque fois que je l'utilise. J'utilise jQuery beaucoup plus fréquemment, c'est pourquoi je cherche quelque chose de similaire. – thebjorn

+1

C'est vraiment très simple. La plupart du temps, tout ce que vous voudrez est 'findAll (nom_tat, nom_classe, attr1 = valeur), etc., avec les valeurs étant 'Aucun' pour ne pas définir, 'Vrai' pour définir, un' str' pour une valeur ou un normal expression de 're.compile'. Ensuite, utilisez simplement les structures d'itération Python normales. Il est différent des sélecteurs CSS, mais il n'est pas difficile à comprendre et à mémoriser et offre plus de puissance dans certaines situations. –

3

Vous voudrez peut-être aussi jeter un oeil à pyquery. pyquery est une librairie de type jquery pour python. Trouver here