【问题标题】:Why my regex doesn't work with BeautifulSoup?为什么我的正则表达式不适用于 BeautifulSoup?
【发布时间】:2017-02-16 17:20:22
【问题描述】:

我正在解析一个 HTML 文件,并希望匹配两个字符序列之间的所有内容:Sent:<br> 标记。

我已经看到了几个非常相似的问题,并尝试了他们所有的方法,但没有一个对我有用,可能是因为我是一个新手并且正在做一些非常简单的错误。

这是我的相关代码:

for filename in os.listdir(path): #capture email year, month, day
    file_path = os.path.join(path, filename)
    if os.path.isfile(file_path):
        with open(file_path, 'r') as f:
            html = f.read()
            soup = BeautifulSoup(html, 'html.parser')
            a = re.findall(r'Sent:/.+?(?=<br>)/', soup.text)[0]
            #a = re.findall(r'Sent:(.*)', soup.text)[0]
            print(a)
            d = parser.parse(a)
            print("year:", d.year)
            print("month:", d.month)
            print("day:", d.day)

我也为我的 RegEx 尝试了这些:a = re.findall(r'Sent:/^(.*?)&lt;br&gt;/', soup.text)[0]a = re.findall(r'Sent:/^[^&lt;br&gt;]*/', soup.text)[0]

但我一直收到错误 list index out of range.... 但即使我删除了 [0] 我在行 AttributeError: 'list' object has no attribute 'read' 上收到错误 d = parser.parse(a)...。只有 [] 打印为print(a)的结果

这是相关的 HTML 块:

<b>Sent:</b> Friday, June 14, 2013 12:07 PM<br><b>To:</b> David Leveille<br><b>Subject:</b> 

【问题讨论】:

    标签: python html regex beautifulsoup


    【解决方案1】:

    问题实际上并不在于您的正则表达式,而是 BeautifulSoup 解析 HTML(毕竟是它的工作)并更改它的内容这一事实。例如,您的&lt;br&gt; 将转换为&lt;br/&gt;。另一点:soup.text 会删除所有标签,因此您的正则表达式将不再起作用。

    试试这个脚本会更清楚:

    from bs4 import *
    import re
    from dateutil import parser
    
    pattern = re.compile(r'Sent:(.+?)(?=<br/>)')
    
    with open("myfile.html", 'r') as f:
            html = f.read()
            print("html: ", html)
            soup = BeautifulSoup(html, 'lxml')
            print("soup.text: ", soup.text)
            print("str(soup): ", str(soup))
            a = pattern.findall(str(soup))[0]
            print("pattern extraction: ", a)
    

    对于第二部分:由于您的日期字符串在形式上不正确(因为最初的&lt;br/&gt;),您应该添加参数fuzzy=True,如documentation of dateutil 中所述。

    d = parser.parse(a, fuzzy=True)
    print("year:", d.year)
    print("month:", d.month)
    print("day:", d.day)
    

    另一种解决方案是使用更精确的正则表达式。例如:

    pattern = re.compile(r'Sent:</b>(.+?)(?=<br/>)')
    

    【讨论】:

    • 哦,好吧,这很有意义。我把它打印出来,看看你在说什么。不过,现在的问题是,我取消了下面的 d = parser.parse(a)print() 语句的注释,但它们仍然因错误 ValueError: Unknown string format 而失败,这已经困扰了我一段时间了
    • 公平地说,我不明白“parser.parse”是什么意思。什么是“解析器”?我知道一个名为“dateparser”的模块,但我无法安装它来尝试。
    • 我被告知要导入 from dateutil import parser....这样我就使用 RegEx 捕获 Sent: 之后的所有内容,然后 parser() 识别并从捕获的内容中捕获日期在Sent: 之后......但是一些电子邮件发生了什么,特别是这封电子邮件,没有\n 字符所以正则表达式搞砸了......所以我注意到在HTML中有一个&lt;br&gt; 在日期信息的末尾,所以我发布了这个问题....现在我发现我基本上处于同样的困境中
    • 好的,我明白了。重要的是要提到所有使用的模块。我已经编辑了我的答案。如果正确,请随时接受或投票。
    • 哇,完美!非常感谢。我什至从未听说过fuzzy 这件事,非常感谢
    【解决方案2】:

    试试这个。如果&lt;br&gt; 标记包含斜杠,它也会考虑在内。

    /Sent:(.*?)<\/*br>/
    

    【讨论】:

    • 所有打印的都是[] :(
    【解决方案3】:

    您不需要通常的斜线转义:

    a = re.findall(r"Sent:(.*?)<br>", soup.text)[0]
    

    话虽如此,在尝试从中获取值之前,您可能应该检查输出(或至少使用 try/except)。

    【讨论】:

      【解决方案4】:

      您能否将您的正则表达式替换为以下查找关键术语以及它们之间的任何内容的正则表达式,并告诉我您现在收到的错误是什么?

      a=re.findall(r"Sent:(.*?)<br>", soup.text)[0]
      

      【讨论】:

      • 只打印[]
      • 尝试在 regxr.com 上。我刚刚做完。为我工作。在这种情况下,问题似乎不是正则表达式。
      • 嗯,这不是好消息...知道为什么会这样失败吗?此代码在另一封 HTML 电子邮件上运行良好,但后来我尝试在这封电子邮件上运行它,所有这些错误都在我尝试仅捕获日期时不断出现
      • 立即尝试,如果仍然无法使用,您可能需要使用 如果您正在寻找 而不是
        请回复我如果这行得通
      猜你喜欢
      • 1970-01-01
      • 2014-01-03
      • 2022-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-05
      • 2011-08-11
      • 1970-01-01
      相关资源
      最近更新 更多