быстрый анализ ссылок на странице в Python - PullRequest
1 голос
/ 03 июня 2011

Мне нужно проанализировать большое количество страниц (скажем, 1000) и заменить ссылки на крошечные ссылки.

сейчас я делаю это с помощью регулярного выражения

href_link_re = re.compile(r"<a[^>]+?href\s*=\s*(\"|')(.*?)\1[^>]*>", re.S)

но это не достаточно быстро.

пока думаю

  1. конечный автомат (успех зависит от моей способности писать умный код)
  2. с использованием html-парсера

Можете ли вы предложить более быстрые способы?

EDIT: Вы можете подумать, что html-парсер будет быстрее, чем регулярное выражение, но в моих тестах это не так:

from BeautifulSoup import BeautifulSoup, SoupStrainer

import re
import time

__author__ = 'misha'

regex = re.compile(r"<a[^>]+?href\s*=\s*(\"|')(.*?)\1[^>]*>", re.S)

def test(text, fn, desc):

    start = time.time()
    total  = 0
    links = [];
    for i in range(0, 10):
        links = fn(text)
        total += len(links)
    end = time.time()
    print(desc % (end-start, total))
   # print(links)

def parseRegex(text):
    links  = set([])
    for link in regex.findall(text):
        links.add(link[1])
    return links

def parseSoup(text):
    links = set([])
    for link in BeautifulSoup(text, parseOnlyThese=SoupStrainer('a')):
        if link.has_key('href'):
            links.add(link['href'])

    return links



if __name__ == '__main__':
    f = open('/Users/misha/test')
    text = ''.join(f.readlines())
    f.close()

    test(text, parseRegex, "regex time taken: %s found links: %s" )
    test(text, parseSoup, "soup time taken: %s found links: %s" )

выход:

regex time taken: 0.00451803207397 found links: 2450
soup time taken: 0.791836977005 found links: 2450

(тест - это дамп главной страницы википедии)

Я, должно быть, плохо использую суп. что я делаю не так?

Ответы [ 2 ]

2 голосов
/ 04 июня 2011

LXML, вероятно, является лучшим выбором для этой задачи.См. Beautiful Soup vs LXML Performance .Синтаксический анализ ссылок в LXML прост и быстр.

root = lxml.html.fromstring(s)
anchors = root.cssselect("a")
links = [a.get("href") for a in anchors]
1 голос
/ 03 июня 2011

Разбор с использованием очень плохой идеи регулярного выражения из-за экспоненциальной временной проблемы со скоростью и регулярным выражением.Вместо этого вы можете использовать парсеры для xhtml.Лучшим является LXML .Или вы можете написать парсер специально для этой цели с парсерами LL, LR.Например: ANTLR , YAPPS , YACC , PYBISON и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...