【问题标题】:Python and re.compile return inconsistent resultsPython 和 re.compile 返回不一致的结果
【发布时间】:2011-01-27 12:37:40
【问题描述】:

我正在尝试用href="../directory/index.html" 替换所有href="../directory" 实例。

在 Python 中,这个

reg = re.compile(r'<a href="../(.*?)">')
for match in re.findall(reg, input_html):
    output_html = input_html.replace(match, match+'index.html')

产生以下输出:

href="../personal-autonomy/index.htmlindex.htmlindex.htmlindex.html"  
href="../paternalism/index.html"  
href="../principle-beneficence/index.htmlindex.htmlindex.html"  
href="../decision-capacity/index.htmlindex.htmlindex.html" 

知道为什么它适用于第二个链接,但其他链接不适用吗?

相关部分出处:

<p> 

 <a href="../personal-autonomy/">autonomy: personal</a> |
 <a href="../principle-beneficence/">beneficence, principle of</a> |
 <a href="../decision-capacity/">decision-making capacity</a> |
 <a href="../legal-obligation/">legal obligation and authority</a> |
 <a href="../paternalism/">paternalism</a> |
 <a href="../identity-personal/">personal identity</a> |
 <a href="../identity-ethics/">personal identity: and ethics</a> |
 <a href="../respect/">respect</a> |
 <a href="../well-being/">well-being</a> 

</p> 

EDIT:重复的'index.html'实际上是多次匹配的结果。 (例如 href="../personal-autonomy/index.htmlindex.htmlindex.htmlindex.html" 是因为 ../personal-autonomy 在原始源中被找到了四次)。

作为一个一般的正则表达式问题,如何在不向所有匹配项添加额外的“index.html”的情况下替换所有实例?

【问题讨论】:

  • 你能告诉我们输入是什么吗?
  • 您为什么要尝试使用正则表达式解析 HTML?有很多强大的解析器可以通过读取 DOM 轻松提取这些语句。正则表达式不是为 HTML 设计的。
  • 一种解决方案:在源 HTML 上运行 .splitlines(),然后在每一行上运行正则表达式,产生了所需的结果。但是,我仍然不确定为什么不拆分就无法工作。

标签: python regex


【解决方案1】:

Don't parse html with regexs:

import re    
from lxml import html

def replace_link(link):
    if re.match(r"\.\./[^/]+/$", link):
        link += "index.html"
    return link

print html.rewrite_links(your_html_text, replace_link)

输出

<p> 

 <a href="../personal-autonomy/index.html">autonomy: personal</a> |
 <a href="../principle-beneficence/index.html">beneficence, principle of</a> |
 <a href="../decision-capacity/index.html">decision-making capacity</a> |
 <a href="../legal-obligation/index.html">legal obligation and authority</a> |
 <a href="../paternalism/index.html">paternalism</a> |
 <a href="../identity-personal/index.html">personal identity</a> |
 <a href="../identity-ethics/index.html">personal identity: and ethics</a> |
 <a href="../respect/index.html">respect</a> |
 <a href="../well-being/index.html">well-being</a> 

</p>

【讨论】:

  • 谢谢你,这很好用,除了完整的输出充满了特殊字符(“等”)。在调用 html.rewrite 之前或之后我需要做些什么吗?
  • @cyrus:将your_html_text 作为Unicode 传递(使用.decode())。使用您的控制台可以理解的编码对 rewrite_links() 的返回值进行编码,例如 s.encode(sys.stdout.encoding or locale.getpreferredencoding())
  • @cyrus: 如果你不知道输入编码,你可以使用stackoverflow.com/questions/2686709/… 的配方,然后调用doc.rewrite_links(replace_links)
  • 感谢您的链接,但我似乎无法使用任何方法对其进行编码。例如,我在 .encode('utf-8') 之前和之后调用 chardet.detect(content)['encoding'] HTML,它仍然显示'ascii'。有什么想法吗?
  • @cyrus:提出一个新问题,描述:您从哪里获得 html(文件、网站)?你在哪里传递它(文件、屏幕、网络)?提供失败输入/输出的示例、重现错误的最少代码、错误/回溯本身。
【解决方案2】:

我想我发现了问题

reg = re.compile(r'&lt;a href="../(.*?)"&gt;')

for match in re.findall(reg, input_html):

output_html = input_html.replace(match, match+'index.html')

这里 'input_html' 在 for 循环中被修改,然后再次搜索相同的 'input_html' 以查找作为 bug 的正则表达式 :)

【讨论】:

  • 使用不同的变量来存储结果
【解决方案3】:

你的领带是否已经逃脱了你的前两个.

reg = re.compile(r'<a[ ]href="[.][.]/(.*?)">')

但我会尝试改用lxml

【讨论】:

  • 在这种情况下为什么重要?
【解决方案4】:

问题是 a-tag 的内容也与您尝试替换的内容相匹配。

这绝不是理想的方法,但我认为如果您将正则表达式替换为以下内容,您会发现它可以正常工作:

reg = re.compile(r'<a href="(\.\./.*?)">')

【讨论】:

    【解决方案5】:

    您的正则表达式中有一个错误,即.. 与两个点不匹配。相反,它是. metacharacter。要表示一个点,您需要对其进行转义。

    您的正则表达式应该是:&lt;a href="\.\./(.*?)"

    此外,假设 all 您的 href 格式为 ../somedirectory/,您可以使用更简单的正则表达式:

    for match in re.compile(r'<a href="(.*?)"').findall(html):
        html = html.replace(match, match + "index.html")
    

    这里,正则表达式匹配

    <a href="    # start of the taf and attribute
    (            # start of a group
     .*          # any character, any number of times
    )            # end of group
    "            # end of the attribute
    

    【讨论】:

    • 谢谢,罗德里格。但是,这仍然会产生相同的输出。
    • 如果标签碰巧在同一行我认为也有点不幸
    • @cyrus 我已经更新了我的答案以提供更多解释。我还注意到我忘记在循环中重新分配html.replace 的输出。我的示例现在有效
    • 另外,罗德里格,?数量之后会要求正则表达式是非贪婪的,即匹配最小的可能组,而不是最大可能的组
    • 至少使用"[^"]+" 而不是"(.*?)"
    猜你喜欢
    • 1970-01-01
    • 2016-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多