2009-11-25 5 views
3

est ici un morceau de code HTML (de délicieux):Python et BeautifulSoup, ne trouvant pas 'a'

<h4> 
<a rel="nofollow" class="taggedlink " href="http://imfy.us/" >Generate Secure Links with Anonymous Referers &amp; Anti-Bot Protection</a> 
<span class="saverem"> 
    <em class="bookmark-actions"> 
    <strong><a class="inlinesave action" href="/save?url=http%3A%2F%2Fimfy.us%2F&amp;title=Generate%20Secure%20Links%20with%20Anonymous%20Referers%20%26%20Anti-Bot%20Protection&amp;jump=%2Fdux&amp;key=fFS4QzJW2lBf4gAtcrbuekRQfTY-&amp;original_user=dux&amp;copyuser=dux&amp;copytags=web+apps+url+security+generator+shortener+anonymous+links">SAVE</a></strong> 
    </em> 
</span> 
</h4> 

Je suis en train de trouver tous les liens où class = "Action inlinesave". Voici le code:

sock = urllib2.urlopen('http://delicious.com/theuser') 
html = sock.read() 
soup = BeautifulSoup(html) 
tags = soup.findAll('a', attrs={'class':'inlinesave action'}) 
print len(tags) 

Mais il ne trouve rien!

Des pensées?

Merci

+1

Qu'advient-il si vous utilisez 'tags = soupe. findAll ('a', attrs = {'class': 'inlinesave'}) 'à la place? –

+0

Hmmm ... ça marche !! Toute explication raisonnable à pourquoi ?? – pns

+1

Les attributs de classe multiples sont séparés par des espaces. L'ancre en question a assigné des classes "inlinesave" et "action". Je suppose que c'est pourquoi la recherche de l'un ou l'autre nom de classe fonctionnera. – Haes

Répondre

1

Si vous voulez chercher un point d'ancrage avec exactement ces deux classes que vous souhaitez, doivent utiliser une expression rationnelle, je pense:

tags = soup.findAll('a', attrs={'class': re.compile(r'\binlinesave\b.*\baction\b')}) 

Gardez à l'esprit que cette regexp a gagné » t travailler si l'ordre des noms de classes est inversé (class="action inlinesave").

La déclaration suivante devrait fonctionner dans tous les cas (même si il semble imo laid.):

soup.findAll('a', 
    attrs={'class': 
     re.compile(r'\baction\b.*\binlinesave\b|\binlinesave\b.*\baction\b') 
    }) 
+0

Cela ne fonctionne que si la regex correspond exactement, donc ce n'est pas mon chemin, personnellement (s'il y a un espace supplémentaire entre les classes, et s'il y a une autre classe entre eux, etc.). Pourrait probablement le resserrer un peu pour correspondre à tous les cas probables bien. –

+0

Vous avez raison, j'ai édité la réponse en conséquence. – Haes

+0

Ceci est décrit comme un bug dans https://bugs.launchpad.net/beautifulsoup/+bug/410304. Peut-être que nous pouvons avoir une solution à l'avenir? – GmonC

0

méthodes de chaîne Python

html=open("file").read() 
for item in html.split("<strong>"): 
    if "class" in item and "inlinesave action" in item: 
     url_with_junk = item.split('href="')[1] 
     m = url_with_junk.index('">') 
     print url_with_junk[:m] 
0

Peut-être problème est résolu dans verion 3.1.0, je pouvais analyser la vôtre,

>>> html="""<h4> 
... <a rel="nofollow" class="taggedlink " href="http://imfy.us/" >Generate Secure Links with Anony 
... <span class="saverem"> 
... <em class="bookmark-actions"> 
...  <strong><a class="inlinesave action" href="/save?url=http%3A%2F%2Fimfy.us%2F&amp;title=Gen 
... </em> 
... </span> 
... </h4>""" 
>>> 
>>> from BeautifulSoup import BeautifulSoup 
>>> soup = BeautifulSoup(html) 
>>> tags = soup.findAll('a', attrs={'class':'inlinesave action'}) 
>>> print len(tags) 
1 
>>> tags 
[<a class="inlinesave action" href="/save?url=http%3A%2F%2Fimfy.us%2F&amp;title=Generate%20Secure% 
>>> 

J'ai essayé avec BeautifulSoup 2.1.1 aussi, son Ça ne foncrionne pas du tout.

0

Vous pourriez faire des progrès vers l'avant en utilisant pyparsing:

from pyparsing import makeHTMLTags, withAttribute 

htmlsrc="""<h4>... etc.""" 

atag = makeHTMLTags("a")[0] 
atag.setParseAction(withAttribute(("class","inlinesave action"))) 

for result in atag.searchString(htmlsrc): 
    print result.href 

Donne (sortie à long résultat snipped à '...'):

/save?url=http%3A%2F%2Fimfy.us%2F&amp;title=Genera...+anonymous+links 
Questions connexes