Как использовать регулярные выражения для парсинга HTML в Java?

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

  • вы проверяете, написано ли "steps 1" в solve.txt, это никогда не может быть так, поскольку S равно как минимум 2 (или более ) и вы проверяете, если steps == S
  • для доступа к шагу N, вы должны были пройти все шаги от 2 до шага N-1 раньше. Это означает, что можно написать что-то вроде кода ниже. Это также сэкономит много ненужной проверки (возможно, меньше можно сделать, зная, в чем проблема, или сэкономив время проверки в памяти):
# since once 'S' isn't found, n >= S will not be in solve.txt
S = 2
while ("steps " + str(S)) in open('solve.txt').read() and S < 8:
    S += 1
  • solve.txt is открывается как минимум 2 раза во время программы, может быть больше, в зависимости от того, сколько вызовов в стеке есть на per1
  • Клаус D показал правильный способ вызова функции, но также обратите внимание, что вы вызываете .start() только когда [ 115] и y = 2002. Это немедленно приводит к тому, что значение result становится равным 0, и, следовательно, результаты не сохраняются (длина 0 равна 1), возвращаясь без ввода-вывода. Вы хотели бы сделать что-то вроде этого (не проверено):
    def driver(start, end, step):
        for i in range(start, end+1, step):
            per1(i)

    p1 = multiprocessing.Process(target=driver, args=(1, 2000, 2))
    p2 = multiprocessing.Process(target=driver, args=(0, 2000, 2))

    p1.start()
    p2.start()

    p1.join()
    p2.join()
  • Также обратите внимание, что многопроцессорный процесс стоит дорого, но он эффективен после запуска, поэтому должен используется, если вы знаете, что ваша программа будет выполняться долго для каждого процесса. Надеюсь, это поможет :)
14
задан Michael Myers 24 March 2009 в 12:35
поделиться

7 ответов

Используя регулярные выражения для получения по запросу значений от HTML всегда ошибка. Синтаксис HTML намного более сложен, что это может сначала появиться, и для страницы очень легко ловить даже очень сложное регулярное выражение.

Используйте Синтаксический анализатор HTML вместо этого. См. также, Каковы за и против ведущего Java синтаксические анализаторы HTML?

53
ответ дан 1 December 2019 в 05:48
поделиться

Вопреки популярному мнению регулярные выражения являются полезными инструментами для извлечения данных из неструктурированного текста (который HTML).

Если Вы делаете, сложное извлечение данных HTML (скажите, найдите все абзацы на странице), затем, парсинг HTML является, вероятно, способом пойти. Но если бы просто необходимо получить некоторые URL от HREFs, затем регулярное выражение хорошо работало бы, и будет очень трудно повредить его.

Попробуйте что-то вроде этого:

/<a[^>]+href=["']?([^'"> ]+)["']?[^>]*>/i
1
ответ дан 1 December 2019 в 05:48
поделиться

Регулярные выражения могут только проанализировать регулярные языки, вот почему их называют регулярными выражениями. HTML не является регулярным языком, следовательно он не может быть проанализирован регулярными выражениями.

Синтаксические анализаторы HTML, с другой стороны, могут проанализировать HTML, вот почему их называют синтаксическими анализаторами HTML.

Необходимо использовать Вас любимый синтаксический анализатор HTML вместо этого.

0
ответ дан 1 December 2019 в 05:48
поделиться

Я искал Библиотеку регулярных выражений (http://regexlib.com/Search.aspx?k=href и http://regexlib.com/Search.aspx?k=src)

Лучшее, которое я нашел, было

((?<html>(href|src)\s*=\s*")|(?<css>url\())(?<url>.*?)(?(html)"|\))

Проверьте эти ссылки для большего количества выражений:

http://regexlib.com/REDetails.aspx?regexp_id=2261

http://regexlib.com/REDetails.aspx?regexp_id=758

http://regexlib.com/REDetails.aspx?regexp_id=774

http://regexlib.com/REDetails.aspx?regexp_id=1437

3
ответ дан 1 December 2019 в 05:48
поделиться

Если Вы хотите спуститься по маршруту парсинга HTML, который Dave и который я рекомендую здесь, является кодом, чтобы проанализировать Строковые Данные для тегов привязки и распечатать их href.

начиная с Ваших просто тегов привязки использования необходимо согласиться только с regex, но если Вы хотите сделать, больше идет с синтаксическим анализатором. Синтаксический анализатор HTML Mozilla является лучшим там.

File parserLibraryFile = new File("lib/MozillaHtmlParser/native/bin/MozillaParser" + EnviromentController.getSharedLibraryExtension());
                String parserLibrary = parserLibraryFile.getAbsolutePath();
                //  mozilla.dist.bin directory :
                final File mozillaDistBinDirectory = new File("lib/MozillaHtmlParser/mozilla.dist.bin."+ EnviromentController.getOperatingSystemName());

        MozillaParser.init(parserLibrary,mozillaDistBinDirectory.getAbsolutePath());
MozillaParser parser = new MozillaParser();
Document domDocument = parser.parse(data);
NodeList list = domDocument.getElementsByTagName("a");

for (int i = 0; i < list.getLength(); i++) {
    Node n = list.item(i);
    NamedNodeMap m = n.getAttributes();
    if (m != null) {
        Node attrNode = m.getNamedItem("href");
        if (attrNode != null)
           System.out.println(attrNode.getNodeValue());
5
ответ дан 1 December 2019 в 05:48
поделиться

Не используйте использование регулярных выражений NekoHTML или TagSoup, которые являются мостом, обеспечивающим SAX или DOM как в подходе XML к посещению документа HTML.

7
ответ дан 1 December 2019 в 05:48
поделиться

Другие ответы верны. Java Regex API не является надлежащим инструментом для достижения цели. Используйте эффективный, безопасный, и хорошо протестировал высокоуровневые инструменты, упомянутые в других ответах.

Если Ваш вопрос касается скорее Regex API, чем реальная проблема (изучение целей, например) - можно сделать это со следующим кодом:

String html = "foo <a href='link1'>bar</a> baz <a href='link2'>qux</a> foo";
Pattern p = Pattern.compile("<a href='(.*?)'>");
Matcher m = p.matcher(html);
while(m.find()) {
   System.out.println(m.group(0));
   System.out.println(m.group(1));
}

И вывод:

<a href='link1'>
link1
<a href='link2'>
link2

Обратите внимание на то, что ленивый/отказанный спецификатор *? должен использоваться для сокращения группировки до единственного тега. Группа 0 является всем соответствием, группа 1 является следующим соответствием группы (следующая пара круглой скобки).

21
ответ дан 1 December 2019 в 05:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: