Получить первую ссылку в статье Википедии не в круглых скобках

Итак, меня интересует эта теорияо том, что если вы перейдете к случайной статье в Википедии, щелкнете по первой ссылке не внутри круглых скобок несколько раз, в 95% случаев случаев вы попадете на статью о Философии.

Я хотел написать скрипт на Python, который извлекает для меня ссылку и, в конце концов, выводит хороший список посещенных статей (linkA -> linkB -> linkC) и т. д.

Мне удалось получить HTML DOM веб-страниц, и мне удалось удалить некоторые ненужные ссылки и верхнюю строку описания, которая ведет к страницам с неоднозначностью. На данный момент я пришел к следующему выводу:

  • DOM начинается с таблицы, которую вы видите справа на некоторых страницах, например, в Human. Мы хотим игнорировать эти ссылки.
  • Все действительные элементы ссылки имеют элемент

    где-то в качестве своего предка (чаще всего родительского или прародительского, если он находится внутри тега или подобного ему. Верхняя панель который ведет на страницы с неоднозначностью, похоже, не содержит никаких элементов

    .
  • Недействительные ссылки содержат некоторые специальные слова, за которыми следует двоеточие, например, Википедия:

Пока, так Хорошо, но меня бесят скобки.Например, в статье о Человекепервая ссылка не в круглых скобках — «/wiki/Species», но скрипт находит «/wiki/Taxonomy», которая находится внутри них.

Я понятия не имею, как это сделать программно, так как мне приходится искать текст в некоторой комбинации родительских/дочерних узлов, которые могут не всегда совпадать. Любые идеи?

Мой код можно увидеть ниже, но это то, что я сделал очень быстро и не очень горжусь этим. Однако он прокомментирован, так что вы можете увидеть ход моих мыслей (надеюсь :)).

"""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  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  tag somewhere inside a .
                    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 

block, so # we dismiss tags which aren't inside any

. 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

задан pg-robban 17 May 2012 в 16:12
поделиться