Я хочу получить значение скрытого поля ввода в HTML.
<input type = "hidden" name = "fooId" value = "12-3456789-1111111111" />
Я хочу написать регулярное выражение на Python, которое вернет значение fooId, учитывая, что я знаю, что строка в HTML следует формату
<input type = "hidden" name = "fooId" value = "**[id is here]**" />
Может ли кто-нибудь предоставить пример на Python для анализа значения HTML?






/<input type = "hidden" name = "fooId" value = "([\d-]+)" />/
Парсинг - одна из тех областей, где вы действительно не хотите кататься самостоятельно, если можете этого избежать, так как вы будете гоняться за крайними случаями и ошибками в течение многих лет.
Я бы рекомендовал использовать BeautifulSoup. Он имеет очень хорошую репутацию и, судя по документации, довольно прост в использовании.
Я люблю регулярные выражения, но должен согласиться с Орионом по этому поводу. Это один из случаев, когда на ум приходит известная цитата Джейми Завински: «Теперь у вас две проблемы».
import re
reg = re.compile('<input type = "hidden" name = "([^"]*)" value = "<id>" />')
value = reg.search(inputHTML).group(1)
print 'Value is', value
В этом конкретном случае BeautifulSoup сложнее написать, чем регулярное выражение, но он намного надежнее ... Я просто добавляю пример BeautifulSoup, учитывая, что вы уже знаете, какое регулярное выражение использовать :-)
from BeautifulSoup import BeautifulSoup
#Or retrieve it from the web, etc.
html_data = open('/yourwebsite/page.html','r').read()
#Create the soup object from the HTML data
soup = BeautifulSoup(html_data)
fooId = soup.find('input',name='fooId',type='hidden') #Find the proper tag
value = fooId.attrs[2][1] #The value of the third attribute of the desired tag
#or index it directly via fooId['value']
Я считаю, что ключевое слово «новое» - несоответствие.
/<input\s+type = "hidden"\s+name = "([A-Za-z0-9_]+)"\s+value = "([A-Za-z0-9_\-]*)"\s*/>/
>>> import re
>>> s = '<input type = "hidden" name = "fooId" value = "12-3456789-1111111111" />'
>>> re.match('<input\s+type = "hidden"\s+name = "([A-Za-z0-9_]+)"\s+value = "([A-Za-z0-9_\-]*)"\s*/>', s).groups()
('fooId', '12-3456789-1111111111')
Я согласен с Винко BeautifulSoup - это то, что нужно. Однако я предлагаю использовать fooId['value'] для получить атрибут, а не полагаться на значение, являющееся третьим атрибутом.
from BeautifulSoup import BeautifulSoup
#Or retrieve it from the web, etc.
html_data = open('/yourwebsite/page.html','r').read()
#Create the soup object from the HTML data
soup = BeautifulSoup(html_data)
fooId = soup.find('input',name='fooId',type='hidden') #Find the proper tag
value = fooId['value'] #The value attribute
Pyparsing - это хороший промежуточный шаг между BeautifulSoup и регулярным выражением. Он более надежен, чем просто регулярные выражения, поскольку его анализ HTML-тегов учитывает варианты регистра, пробелов, наличия / отсутствия / порядка атрибутов, но этот тип базового извлечения тегов проще, чем использование BS.
Ваш пример особенно прост, поскольку все, что вы ищете, находится в атрибутах открывающего тега «input». Вот пример pyparsing, показывающий несколько вариантов вашего входного тега, которые будут соответствовать регулярным выражениям, а также показывает, как НЕ сопоставлять тег, если он находится в комментарии:
html = """<html><body>
<input type = "hidden" name = "fooId" value = "**[id is here]**" />
<blah>
<input name = "fooId" type = "hidden" value = "**[id is here too]**" />
<input NAME = "fooId" type = "hidden" value = "**[id is HERE too]**" />
<INPUT NAME = "fooId" type = "hidden" value = "**[and id is even here TOO]**" />
<!--
<input type = "hidden" name = "fooId" value = "**[don't report this id]**" />
-->
<foo>
</body></html>"""
from pyparsing import makeHTMLTags, withAttribute, htmlComment
# use makeHTMLTags to create tag expression - makeHTMLTags returns expressions for
# opening and closing tags, we're only interested in the opening tag
inputTag = makeHTMLTags("input")[0]
# only want input tags with special attributes
inputTag.setParseAction(withAttribute(type = "hidden", name = "fooId"))
# don't report tags that are commented out
inputTag.ignore(htmlComment)
# use searchString to skip through the input
foundTags = inputTag.searchString(html)
# dump out first result to show all returned tags and attributes
print foundTags[0].dump()
print
# print out the value attribute for all matched tags
for inpTag in foundTags:
print inpTag.value
Печать:
['input', ['type', 'hidden'], ['name', 'fooId'], ['value', '**[id is here]**'], True]
- empty: True
- name: fooId
- startInput: ['input', ['type', 'hidden'], ['name', 'fooId'], ['value', '**[id is here]**'], True]
- empty: True
- name: fooId
- type: hidden
- value: **[id is here]**
- type: hidden
- value: **[id is here]**
**[id is here]**
**[id is here too]**
**[id is HERE too]**
**[and id is even here TOO]**
Вы можете видеть, что pyparsing не только соответствует этим непредсказуемым вариациям, но и возвращает данные в объекте, что упрощает считывание отдельных атрибутов тегов и их значений.
Я согласен с общим случаем, но если вы делаете разовый сценарий для анализа одной или двух очень конкретных вещей, регулярное выражение может просто облегчить жизнь. Очевидно, более хрупкий, но если ремонтопригодность не является проблемой, то это не проблема. Тем не менее, BeautifulSoup - это фантастика.