Извлечение URL из больших текстовых / HTML файлов - PullRequest
5 голосов
/ 12 февраля 2012

У меня много текста, который мне нужно обработать для получения действительных URL-адресов.

Ввод смутно HTMLish, в основном это HTML.Тем не менее, это не совсем действительный HTML.

Я * пытался сделать это с помощью регулярных выражений и у меня возникли проблемы.

Прежде чем вы скажете (или, возможно, закричите - япрочитал другие вопросы HTML + regex) " использовать парсер ", есть одна вещь, которую вам нужно учитывать:
Файлы, с которыми я работаю, имеют размер около 5 ГБ

Я не знаю ни одного парсера, который мог бы справиться с этим без сбоев или нескольких дней.Кроме того, тот факт, что, хотя текстовое содержимое является в значительной степени html, но не обязательно valid html, означает, что для него потребуется очень терпимый синтаксический анализатор.Наконец, не все ссылки обязательно должны быть в <a> тегах (некоторые могут быть просто открытым текстом).

Учитывая то, что меня не очень интересует структура документа, есть ли лучшие альтернативы извлечения ссылок WRT?

Прямо сейчас я использую регулярное выражение:
\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))) (в grep -E)
, но даже после этого я сдался, дав ему поработать около 3 часов.

Существуют ли существенные различия в производительности двигателя Regex?Я использую командную строку MacOS grep.Если есть другие совместимые реализации с лучшей производительностью, это может быть вариантом.


Я не слишком беспокоюсь о языке / платформе, хотя MacOS / командная строка были бы хорошими.

Ответы [ 2 ]

2 голосов
/ 25 февраля 2012

Я завел пару команд grep вместе:

pv -cN source allContent | grep -oP "(?:\"([^\"' ]*?)\")|(?:'([^\"' ]*?)')|(?:([^\"' ]*?) )" | grep -E "(http)|(www)|(\.com)|(\.net)|(\.to)|(\.cc)|(\.info)|(\.org)" | pv -cN out > extrLinks1

Я использовал pv, чтобы дать мне индикатор прогресса.

grep -oP "(?:\"([^\"' ]*?)\")|(?:'([^\"' ]*?)')|(?:([^\"' ]*?) )"
Извлекает все, что выглядит как слово или текст в кавычках, без пробелов.

grep -E "(http)|(www)|(\.com)|(\.net)|(\.to)|(\.cc)|(\.info)|(\.org)"
Фильтрует выходные данные для всего, что выглядит как URL.

Наконец,
pv -cN out > extrLinks1
Выводит его в файл и дает хороший индикатор активности.

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


В любом случае, поскольку он работает прямо сейчас, похоже, это займет около 40 минут. Я не знал о pv раньше. Это действительно крутая утилита!

0 голосов
/ 12 февраля 2012

Я думаю, что вы на правильном пути, и grep должен уметь обрабатывать файл 5 Гб.Попробуйте упростить свое регулярное выражение, избегая оператора | и множества круглых скобок.Кроме того, используйте команду head, чтобы захватить первые 100 КБ перед запуском по всему файлу, и объединить команды grep, используя каналы для достижения большей специфичности.Например,

head -c 100000 myFile | grep -E "((src)|(href))\b*=\b*[\"'][\w://\.]+[\"']"

Это должно быть супер быстро, нет?

...