Новичок Python / Regex: тянуть строки между тегами <a>, используя регулярное выражение - PullRequest
1 голос
/ 27 декабря 2011

Необходимо вытащить строки между тегами атрибутов href в Python, используя модуль re.

Я пробовал многочисленные шаблоны, такие как:

patFinderLink = re.compile('\>"(CVE.*)"\<\/a>')

Пример: мне нужно вытащить то, что находится между тегами (в данном случае " CVE-2010-3718 ") из:

<code><pre>
<a href="https://www.redhat.com/security/data/cve/CVE-2010-3718.html">CVE-2010-3718</a>

Что я здесь не так делаю? Любые советы высоко ценится. Заранее спасибо.

ВС

Ответы [ 6 ]

6 голосов
/ 27 декабря 2011

Вам нужно использовать регулярные выражения? Я не думаю, что вы делаете, вы не можете анализировать SGML с регулярными выражениями, потому что сам SGML не является регулярным, см. Этот известный ответ stackoverflow для рассуждения: https://stackoverflow.com/a/1732454/88123

Так или иначе. Вы должны использовать модуль lxml Python и его реализацию xpath. xpath поддерживает выбор с текстом, который начинается с.

XPath в этом случае будет //h1/text().

Или используйте модуль Python BeautifulSoup.

2 голосов
/ 27 декабря 2011

Не пытайтесь использовать регулярные выражения для разбора HTML или XML.Используйте такой синтаксический анализатор, как lxml.

import lxml.html as lh

tree = lh.fromstring(html)

print tree.xpath("//pre/a[starts-with(., 'CVE')]/text()")

Результат:

['CVE-2010-3718']
1 голос
/ 27 декабря 2011

Используйте

re.compile('">(CVE.*?)</a>') 

# instead of your re.compile('\>"(CVE.*)"\<\/a>')

Обратите внимание, что символы <> / не нужно экранировать в шаблоне регулярных выражений

И обратите внимание, что символ ? после .* останавливает жадное поведение квантификатора * для того, чтобы совпадение прекратилось, когда был принят первый </a>. Смотрите документы по этому вопросу, это фундаментально

.

Иногда возникают проблемы при использовании re для анализа текста XML | GML
Однажды мне сказали, что одна из возможных проблем заключается в том, что тег может быть записан в несколько строк, например:

<code>ss = '''
<pre>
    <a href="https://www.redhat.com/security/data/cve/CVE-2010-3718.html">CVE-20
    10-371
    8</a>
''»

В этом случае совпадения не будет, потому что точка, используемая в качестве символа в шаблоне регулярного выражения, не символизирует символ новой строки '\ n'. Таким образом, часть .*? шаблона не будет позволять переходить от строки к строке.

Чтобы исправить эту проблему, используйте спецификацию re.DOTALL, которая дает символу точки возможность представлять любые символы.

.

Обратите внимание, что по общему убеждению инструмент re не должен использоваться для анализа текста SGML или XML. Но мало кто в состоянии объяснить, почему. И я один из тех людей, которые точно не знают, почему.

Но лично я думаю, что регулярное выражение может действительно использоваться для анализа текстов. Я пишу «АНАЛИЗ», а не «ПАРС».

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

0 голосов
/ 28 декабря 2011

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

Но если вы хотите использовать регулярное выражение, это пример того, как я мог бы извлечь все кортежи как URL, так исодержимое между тегами <a> </a>:

<code>import re

#example html string with various hits
html_string = """
    <pre>
    <a href="https://www.redhat.com/security/data/cve/CVE-2010-3718.html">CVE-2010-3718</a>
    <a href="https://www.redhat.com/security/data/cve/CVE-2010-3710.html">CVE-2010-3710</a>
    <a href="https://www.redhat.com/security/data/cve/CVE-2010-3700.html">CVE-2010-3700</a>
"" "#regular expression: pattern = re.compile (' ] *)> ([^ <] *) </a>') # найти все совпадения в нашемстрока html: tuples = pattern.findall (html_string) для кортежа в кортежах: print "% s ->% s"% (tuple [1], tuple [0])

Как уже упоминалосьlxml был бы более подходящим инструментом.

Если вы собираетесь сделать это таким образом, я рекомендую вам следовать ответу @Acorn.

0 голосов
/ 27 декабря 2011

Я удивлен, что никто не предложил использовать BeautifulSoup:

вот как бы я это сделал:

<code>from BeautifulSoup import BeautifulSoup
import re

hello = """
<pre>
<a href="https://www.redhat.com/security/data/cve/CVE-2010-3718.html">CVE-2010-3718</a>
<a href="https://www.redhat.com/security/data/cve/CVE-2010-3710.html">CVE-2010-3718</a>
<a href="https://www.redhat.com/security/data/cve/CVE-2010-3700.html">CVE-2010-3718</a>
«»» target = re.compile ("CVE- \ d + - \ d + .html") commentSoup = BeautifulSoup (привет) atags = commentSoup.findAll (href = target) для atags: match = re.findall (target, a ['href']) [0] печать матча

Результат:

CVE-2010-3718.html
CVE-2010-3710.html
CVE-2010-3700.html
0 голосов
/ 27 декабря 2011

Если вы все еще хотите использовать регулярные выражения для разбора HTML (хотя это не рекомендуется, как уже упоминалось ранее - но я не знаю почему), попробуйте это:

a = re.compile('<a href=".*">(.*)</a>')
result = a.match(string).group(0)

результат будет содержать CVE-2010-3718

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