So interessiert mich this theory, dass, wenn Sie zu einem zufälligen Wikipedia-Artikel gehen, klicken Sie auf den ersten Link nicht in Klammern wiederholt, in 95% der Fälle werden Sie am Ende auf den Artikel über Philosophy.Erhalten Sie den ersten Link in einem Wikipedia-Artikel nicht in Klammern
Ich wollte einen Skript in Python schreiben, die auf den Link für mich holen tun und am Ende eine schöne Liste drucken, von denen Artikel besucht wurden (linkA -> linkB -> linkC
) usw.
ich von dem HTML-DOM bekommen verwaltet die Webseiten, und schaffte es, einige unnötige Links und die obere Beschreibungsleiste, die Disambiguierungsseiten führt, zu entfernen. Bisher habe ich festgestellt, dass:
- Das DOM beginnt mit der Tabelle, die Sie auf einigen Seiten rechts sehen, zum Beispiel in Human. Wir möchten diese Links ignorieren.
- Die gültigen Verbindungselemente verfügen alle über ein
<p>
Element irgendwo als ihre Vorfahren (meist Eltern oder Großeltern, wenn es in einem<b>
Tag oder ähnlich ist. Der obere Balken, die zu Begriffsklärung Seiten führt, scheint keine<p>
Elemente enthalten. - Ungültige Links enthalten einige spezielle Wörter mit einem Doppelpunkt, zB
Wikipedia:
so weit, so gut. Aber es ist die Klammern, die mich zu bekommen. In dem Artikel über Human zum Beispiel das erste Glied nicht in Klammern ist "/ wiki/Species", aber das Skript findet "/ wiki/Taxonomy", das in ihnen ist.
Ich habe keine Ahnung, wie ich das programmatisch angehen soll, da ich in einer Kombination von Eltern/Kind-Knoten nach Text suchen muss, der nicht immer derselbe ist. Irgendwelche Ideen?
Mein Code kann unten gesehen werden, aber es ist etwas, das ich wirklich schnell gemacht habe und nicht sehr stolz darauf bin. Es ist jedoch kommentiert, so dass Sie meine Gedanken sehen können (ich hoffe :)).
"""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
Vielleicht möchten Sie die reichere Benutzeroberfläche von lxml ausprobieren. Das erlaubt dir, XPath und eine Menge anderer Dinge zu benutzen. – Marcin
Während wir auf Empfehlungen sind, würde ich gerne beautifulsoup als ein wahrscheinlich hilfreicher Name hier fallen lassen. – marue
@marue Zwei tolle Geschmäcker, die gut zusammen schmecken: lxml hat ein wunderschönes Backend! – Marcin