быстрый анализ ссылок на странице в Python

1

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

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

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

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

Я сейчас думаю

  • state machine (успех этого будет зависеть от моей способности писать умный код)
  • с помощью анализатора 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

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

Я должен плохо использовать суп. Что я делаю неправильно?

  • 0
    Не могли бы вы упростить свой код, сначала ища <a а затем проверяя совпадения позже.
  • 0
    да, и это был бы конечный автомат
Показать ещё 1 комментарий
Теги:
parsing
beautifulsoup

2 ответа

2
Лучший ответ

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

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

  • 2
    Я помню эту легендарную SO-статью каждый раз, когда публикуется вопрос об использовании регулярных выражений для разбора html. stackoverflow.com/questions/1732348/...
  • 0
    Что быстрее: LXML или Beautiful Soup? Я пользуюсь последним, но похоже, что в наши дни рекомендую первое чаще
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню