%%time
link_parser = LinkParser()
to_visit = {"https://simple.wikipedia.org/wiki/Main_Page"}  # starting url
visited = set()
graph = nx.DiGraph()
bad_urls = []

def spider(delay=0.1):
    global link_parser, to_visit, visited, graph
    while len(to_visit):
        url = to_visit.pop()
        logging.info("%s: %s", len(visited), url)
        graph.add_node(url)
        visited.add(url)
        try:
            links = link_parser.get_links(url)
        except Exception as e:
            print e
            logging.error(e)
            bad_urls.append(url)
            continue        
        to_visit = to_visit.union(links - visited)
        graph.add_edges_from(zip([url] * len(links), links))
        sleep(delay)

spider(0.01)

"""
Explanation: На этапе фильтрации при помощи регулярного выражения отбираются url-ы, ведущие на уникальные вики-страницы. Эти страницы имеют доменное имя simple.wikipedia.org и лежат по пути wiki. По интересующему пути simple.wikipedia.org/wiki/ также лежат служебные страницы, начинающиеся на File:, Help:, Special: и т.д., которые отбрасываются во время фильтрации (при этом нельзя отбрасывать любой url с символом ':', т.к. существуют такие страницы, как "ISO_3166-2:BR" или "Star_Trek:_Phase_II"). Ещё одним особым случаем является url по вышеуказанному пути, чья уникальная часть начинается на символ '#' (например, simple.wikipedia.org/wiki/#blabla) - такой url редиректит на главную страницу. Его также считаем невалидным (*встретился после посещения половины всех страниц при самом первом заходе).
На этапе нормализации из url-а отбрасывается часть, начинающаяся с хештега, т.к. она содержит в себе лишь информацию об определённом положении на странице. Также отсекается внутренний путь страницы, идущий за слешем после названия страницы.
При обходе поддерживаются множества url-ов to_visit и visited (в первом не могут содержаться объекты из второго). Также во время обхода строится ориентированный граф из страниц для дальнейшего вычисления PageRank-а.
End of explanation
"""


graph.remove_nodes_from(bad_urls)

graph.number_of_nodes()

"""
Explanation: Как видно, у небольшого числа урлов оказалась проблема с кодировкой, дропнем их из графа. И посмотрим сколько страниц нашли.
End of explanation
"""


%%time
pagerank = nx.pagerank(graph)

top20 = [0.] * 20
for url, rank in pagerank.iteritems():
    heappushpop(top20, (rank, url))

while top20:
    rank, url = heappop(top20)
    print rank, url

"""
Explanation: 135318 из 123771 уникальных страниц. Предполагаю, что причина превосходства числа найденных страниц связанно с наличием редиректов, которые не предлагалось обрабатывать.
Посчитаем PageRank и найдём 20 топовых страниц.
End of explanation
"""


