write - Ottenere il valore degli attributi href in tutti i tag<a> su un file html con Python




xml etree elementtree write (5)

Bene, solo per completezza aggiungerò qui quella che ho trovato la migliore risposta, e l'ho trovata nel libro Dive Into Python, di Mark Pilgrim.

Segue il codice per elencare tutti gli URL da una pagina Web:

from sgmllib import SGMLParser

class URLLister(SGMLParser):
    def reset(self):                              
        SGMLParser.reset(self)
        self.urls = []

    def start_a(self, attrs):                     
        href = [v for k, v in attrs if k=='href']  
        if href:
            self.urls.extend(href)

import urllib, urllister
usock = urllib.urlopen("http://diveintopython.net/")
parser = urllister.URLLister()
parser.feed(usock.read())         
usock.close()      
parser.close()                    
for url in parser.urls: print url

Grazie per tutte le risposte.

https://code.i-harness.com

Sto costruendo un'applicazione in python e ho bisogno di ottenere l'URL di tutti i link in una pagina web. Ho già una funzione che utilizza urllib per scaricare il file html dal web e trasformarlo in un elenco di stringhe con readlines ().

Attualmente ho questo codice che usa regex (non sono molto bravo a farlo) per cercare i collegamenti in ogni riga:

for line in lines:
    result = re.match ('/href="(.*)"/iU', line)
    print result

Questo non funziona, poiché stampa solo "None" per ogni riga del file, ma sono sicuro che almeno ci siano 3 link nel file che sto aprendo.

Qualcuno può darmi un suggerimento su questo?

Grazie in anticipo


C'è un parser HTML che viene fornito di serie in Python. Checkout htmllib .


Come accennato in precedenza: regex non ha il potere di analizzare HTML. Non usare espressioni regolari per l'analisi dell'HTML. Non passare Go. Non raccogliere £ 200.

Usa un parser HTML.

Ma per completezza, il problema principale è:

re.match ('/href="(.*)"/iU', line)

Non si utilizza la sintassi "/.../flags" per decorare espressioni regex in Python. Invece metti le bandiere in un argomento separato:

re.match('href="(.*)"', line, re.I|re.U)

Un altro problema è il modello avido '. *'. Se hai due hrefs in una riga, succhierà felicemente tutto il contenuto tra l'apertura "della prima partita e la chiusura" della seconda partita. Puoi usare il non-goloso '. *?' o, più semplicemente, '[^ "] *' solo per abbinare fino alla prima quotazione di chiusura.

Ma non utilizzare espressioni regex per l'analisi di HTML. Veramente.


Non dividere il contenuto html in linee, poiché potrebbero esistere più corrispondenze in una singola riga. Inoltre, non dare per scontato che ci siano sempre citazioni sull'URL.

Fai qualcosa del genere:

links = re.finditer(' href="?([^\s^"]+)', content)

for link in links:
  print link

La bella zuppa può farlo quasi banalmente:

from BeautifulSoup import BeautifulSoup as soup

html = soup('<body><a href="123">qwe</a><a href="456">asd</a></body>')
print [tag.attrMap['href'] for tag in html.findAll('a', {'href': True})]




parsing