python 正则匹配,findall 或 search 不返回值
我正在尝试从一个字符串中找到一个标记并返回它。我在其他字符串上使用这个方法时效果很好,但这个字符串似乎没有返回任何结果。无论是用findall还是search都不行。
pattern= re.compile(r'<input class="token" value="(.+?)" name="csrftoken_reply">')
matches = pattern.findall(htmlstring)
for match in matches:
print match
每个响应字符串中只有一个值,但我没有得到“打印匹配”的结果。
我也尝试过使用re.search,但结果还是一样,返回的是一个NoneType对象……
更多信息:
这是我正在解析的HTML的一部分:
<form id="threadReplyForm" class="clearfix" method="post" action="/go/messages/private/threadID=0551796">
<input class="csrftoken" type="hidden" value="a7b161b7" name="csrftoken_reply">
<input type="hidden" value="reply" name="action">
<div class="editorWrapper">
<div id="premiumSmiliesNotAllowed" class="warning" style="display: none;">
<div id="editor_13" class="clearfix editor" mode="full">
<ul id="editorToolbar_13" class="editorToolbar clearfix">
<textarea id="messageInput" class="autogrow" cols="20" rows="8" name="message"></textarea>
<div id="previewDiv" class="previewArea" style="display: none;"></div>
</div>
<script>
</div>
<script>
<span class="loadingIndicator right loadingIndicatorMessage">
<p class="clearfix">
</form>
我用这个来解析:
pattern= re.compile(r'<input class="csrftoken" type="hidden" value="(.+?)" name="csrftoken_reply">')
matches = pattern.findall(str(response.read()))
for match in matches:
print match
我想要的输出是a7b161b7
3 个回答
抱歉,2011年用正则表达式解析HTML简直是疯狂 :) 现在有很多专门为这个任务优化的库,其中最好的就是上面提到的BeautifulSoup和lxml。我能理解你不想用lxml,因为它的依赖项很多,安装起来也很麻烦,但BeautifulSoup只需要一个文件,能让你的代码更加稳定。
总结一下:你是在重复造轮子。
你需要给出一个你想要解析的字符串示例,因为对我来说这个是有效的。
import re
htmlstring = """
<input class="token" value="foo" name="csrftoken_reply">
"""
pattern= re.compile(r'<input class="token" value="(.+?)" name="csrftoken_reply">')
matches = pattern.findall(htmlstring)
for match in matches:
print match
除此之外,你有没有考虑过使用一些专门为这种情况设计的库?使用正则表达式解析HTML可能会比较脆弱。Beautiful Soup似乎是一个很受欢迎的工具。
更新
你有一个错误的类值,还有一个多余的空格,并且你忘记了 'input type="hidden"'。这里有一个更接近的例子,不过我还是不建议使用正则表达式:
r'<input class="csrftoken" type="hidden" value="(.+?)" name="csrftoken_reply">'
这个也可以用(我假设只有一个 'csrftoken_reply' 元素):
r'value="(.+?)" name="csrftoken_reply">'
这两种方法都能帮你获取到想要的值。
我不是Python专家,也不推荐用正则表达式来解析HTML,但这样做可能可以获取无序的属性-值数据。只需要放入一些必要的键值对来确定标签的类型。并不需要全部的键值对,也不需要按特定顺序。
修饰符:扩展、单行字符串、全局。
值捕获组是$5。
编辑
我把(?= (?:".*?"|\'.*?\'|[^>]*?)+
改成了(?= (?:[^>"\']|(?>".*?"|\'.*?\'))*?
,因为这种形式的懒惰量词会被迫超出标记边界来满足前瞻条件。新的子表达式可以处理attr="so< m >e"
中嵌入的标记,而不会出现超出的问题。
<input
(?=\s)
(?= (?:[^>"\']|(?>".*?"|\'.*?\'))*? (?<=\s) class \s*=\s* ([\'"]) \s* csrftoken \s*\1 )
(?= (?:[^>"\']|(?>".*?"|\'.*?\'))*? (?<=\s) name \s*=\s* ([\'"]) \s* csrftoken_reply \s*\2 )
(?= (?:[^>"\']|(?>".*?"|\'.*?\'))*? (?<=\s) type \s*=\s* ([\'"]) \s* hidden \s*\3 )
(?= (?:[^>"\']|(?>".*?"|\'.*?\'))*? (?<=\s) value \s*=\s* ([\'"]) \s* (.*?) \s*\4 )
\s+ (?:".*?"|\'.*?\'|[^>]*?)+ (?<!/)
>
所有的注意事项都适用,可能会隐藏在嵌入的代码中,可能是注释等等...
对此需要额外的正则逻辑。