为什么我的正则表达式不能与BeautifulSoup一起使用?

时间:2017-02-16 17:20:22

标签: python html regex beautifulsoup

我正在解析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:/^(.*?)<br>/', soup.text)[0]a = re.findall(r'Sent:/^[^<br>]*/', 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> 

4 个答案:

答案 0 :(得分:1)

请问您的正则表达式是否可以替换下面的正则表达式,以查找关键术语,然后介绍它们之间的任何内容,并告诉我您现在收到的错误是什么?

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

答案 1 :(得分:1)

试试这个。它还会考虑<br>标记是否包含斜杠。

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

答案 2 :(得分:1)

你不需要通常的斜线逃脱:

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

话虽这么说,你应该在尝试从中获取值之前检查输出(或者至少使用try / except)。

答案 3 :(得分:1)

问题不是你的正则表达式,而是BeautifulSoup解析HTML(毕竟它的工作)和更改其内容的事实。例如,您的<br>将转换为<br/>。另一点: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)

对于第二部分:由于您的日期字符串不正式(因为初始<br/>),您应该添加参数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/>)')