2012-06-06 6 views
5

Sto lavorando a un progetto in cui ho bisogno di un po 'di raschiatura. Il progetto è su Google App Engine e attualmente utilizziamo Python 2.5. Idealmente, useremmo PyQuery ma a causa di esecuzione su App Engine e Python 2.5, questa non è un'opzione.Come posso emulare ": contains" usando BeautifulSoup?

Ho visto domande come questa su finding an HTML tag with certain text, ma non hanno abbastanza colpito nel segno.

ho qualche HTML che assomiglia a questo:

<div class="post"> 
    <div class="description"> 
     This post is about <a href="http://www.wikipedia.org">Wikipedia.org</a> 
    </div> 
</div> 
<!-- More posts of similar format --> 

In PyQuery, avrei potuto fare qualcosa di simile (per quanto ne so):

s = pq(html) 
s(".post:contains('This post is about Wikipedia.org')") 
# returns all posts containing that text 

Ingenuamente, ho avuto però che Potrei fare qualcosa del genere in BeautifulSoup:

soup = BeautifulSoup(html) 
soup.findAll(True, "post", text=("This post is about Google.com")) 
# [] 

Tuttavia, questo non ha prodotto risultati. Ho cambiato la mia query per utilizzare un'espressione regolare, e ottenuto un po 'più lontano, ma ancora senza fortuna:

soup.findAll(True, "post", text=re.compile(".*This post is about.*Google.com.*")) 
# [] 

funziona se tralascio Google.com, ma poi ho bisogno di fare tutto il filtraggio manualmente. È comunque necessario emulare :contains utilizzando BeautifulSoup?

alternativa, c'è qualche libreria PyQuery simile che funziona su App Engine (su Python 2.5)?

+0

Perché non si passa alla 2.7 dove [lxml è disponibile] (https://developers.google.com/appengine/docs/python/python27/newin27#Supported_Third-Party_Libraries)? – schlamar

+0

Vogliamo sicuramente, non siamo ancora riusciti a farlo. Vecchia base di codice, non abbastanza tempo, ecc. È una critica giusta. – NT3RP

+0

Bene, la [migrazione] (https://developers.google.com/appengine/docs/python/python27/using27#Considerations_When_Migrating_Your_Application) non sembra troppo complessa e poiché le tue applicazioni sono versionate puoi semplicemente fare un tentativo e tornare indietro se non funziona – schlamar

risposta

5

Dalla documentazione BeautifulSoup (sottolineatura mia):

"text è un argomento che ti permette di cercare NavigableString oggetti invece di Tag"

vale a dire, la vostra codice:

soup.findAll(True, "post", text=re.compile(".*This post is about.*Google.com.*")) 

non è la stessa:

regex = re.compile('.*This post is about.*Google.com.*') 
[post for post in soup.findAll(True, 'post') if regex.match(post.text)] 

Il motivo è necessario rimuovere la Google.com è che non c'è un oggetto NavigableString nell'albero BeautifulSoup per "This post is about", e un altro per "Google.com", ma sono sotto elementi diversi.

Per inciso, post.text esiste ma non è documentato, quindi non mi fiderei nemmeno di quello, ho scritto quel codice per sbaglio! Usa altri mezzi per mettere insieme tutti i messaggi sotto post.

+1

Ho letto sicuramente quella citazione, ma non ho capito la differenza.Questo è sicuramente ciò di cui avevo bisogno.Grazie :) – NT3RP

+0

@ NT3RP "couldn capisco la differenza ": lo stesso per me, la documentazione di BeautifulSoup è davvero un disastro. ;) – schlamar