Quindi sono interessato allo this theory che se vai su un articolo di Wikipedia a caso, fai clic sul primo collegamento non tra parentesi ripetutamente, nel 95% dei casi finirai per sull'articolo Philosophy.Ottieni il primo link in un articolo di Wikipedia non tra parentesi
ho voluto scrivere uno script in Python che fa il collegamento recupero per me e alla fine, stampare una bella lista di cui sono stati visitati articoli (linkA -> linkB -> linkC
) ecc
sono riuscito ad ottenere il DOM HTML le pagine web e sono riuscito a rimuovere alcuni collegamenti non necessari e la barra di descrizione superiore che conduce alle pagine di disambiguazione. Finora ho concluso che:
- Il DOM inizia con la tabella che vedi a destra su alcune pagine, ad esempio in Human. Vogliamo ignorare questi collegamenti.
- Gli elementi di collegamento validi tutti hanno un elemento
<p>
da qualche parte come il loro antenato (il più delle volte genitore o un nonno se è all'interno di un tag<b>
o simile. La barra superiore che porta a pagine di disambiguazione, non sembra contenere<p>
elementi. - collegamenti non validi contengono alcuni parole speciali seguita da due punti, ad esempio
Wikipedia:
Fin qui, tutto bene. Ma è la parentesi che mi ottengono. Nell'articolo su Human per esempio, il primo link parentesi non è dentro "/ wiki/Species", ma lo script trova "/ wiki/Taxonomy" che si trova all'interno di essi.
Non ho idea di come procedere a livello di programmazione, poiché devo cercare il testo in una combinazione di nodi padre/figlio che potrebbe non essere sempre lo stesso. Qualche idea?
Il mio codice può essere visto sotto, ma è qualcosa che ho inventato molto rapidamente e non molto orgoglioso di. È stato commentato comunque, quindi puoi vedere la mia linea di pensiero (spero :)).
"""Wikipedia fun"""
import urllib2
from xml.dom.minidom import parseString
import time
def validWikiArticleLinkString(href):
""" Takes a string and returns True if it contains the substring
'/wiki/' in the beginning and does not contain any of the
"special" wiki pages.
"""
return (href.find("/wiki/") == 0
and href.find("(disambiguation)") == -1
and href.find("File:") == -1
and href.find("Wikipedia:") == -1
and href.find("Portal:") == -1
and href.find("Special:") == -1
and href.find("Help:") == -1
and href.find("Template_talk:") == -1
and href.find("Template:") == -1
and href.find("Talk:") == -1
and href.find("Category:") == -1
and href.find("Bibcode") == -1
and href.find("Main_Page") == -1)
if __name__ == "__main__":
visited = [] # a list of visited links. used to avoid getting into loops
opener = urllib2.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')] # need headers for the api
currentPage = "Human" # the page to start with
while True:
infile = opener.open('http://en.wikipedia.org/w/index.php?title=%s&printable=yes' % currentPage)
html = infile.read() # retrieve the contents of the wiki page we are at
htmlDOM = parseString(html) # get the DOM of the parsed HTML
aTags = htmlDOM.getElementsByTagName("a") # find all <a> tags
for tag in aTags:
if "href" in tag.attributes.keys(): # see if we have the href attribute in the tag
href = tag.attributes["href"].value # get the value of the href attribute
if validWikiArticleLinkString(href): # if we have one of the link types we are looking for
# Now come the tricky parts. We want to look for links in the main content area only,
# and we want the first link not in parentheses.
# assume the link is valid.
invalid = False
# tables which appear to the right on the site appear first in the DOM, so we need to make sure
# we are not looking at a <a> tag somewhere inside a <table>.
pn = tag.parentNode
while pn is not None:
if str(pn).find("table at") >= 0:
invalid = True
break
else:
pn = pn.parentNode
if invalid: # go to next link
continue
# Next we look at the descriptive texts above the article, if any; e.g
# This article is about .... or For other uses, see ... (disambiguation).
# These kinds of links will lead into loops so we classify them as invalid.
# We notice that this text does not appear to be inside a <p> block, so
# we dismiss <a> tags which aren't inside any <p>.
pnode = tag.parentNode
while pnode is not None:
if str(pnode).find("p at") >= 0:
break
pnode = pnode.parentNode
# If we have reached the root node, which has parentNode None, we classify the
# link as invalid.
if pnode is None:
invalid = True
if invalid:
continue
###### this is where I got stuck:
# now we need to look if the link is inside parentheses. below is some junk
# for elem in tag.parentNode.childNodes:
# while elem.firstChild is not None:
# elem = elem.firstChid
# print elem.nodeValue
print href # this will be the next link
newLink = href[6:] # except for the /wiki/ part
break
# if we have been to this link before, break the loop
if newLink in visited:
print "Stuck in loop."
break
# or if we have reached Philosophy
elif newLink == "Philosophy":
print "Ended up in Philosophy."
break
else:
visited.append(currentPage) # mark this currentPage as visited
currentPage = newLink # make the the currentPage we found the new page to fetch
time.sleep(5) # sleep some to see results as debug
Potresti provare l'interfaccia più completa fornita da lxml. Questo ti permette di usare xpath e un sacco di altre cose. – Marcin
Mentre ci occupiamo di consigli, mi piacerebbe far cadere beautifulsoup come un nome probabilmente utile qui. – marue
@marue Due grandi sapori che hanno un ottimo sapore insieme: lxml ha un backend bellissimo! – Marcin