从 python 中的网页集合中快速抓取 html 标签的方法

Fast way to scrape html tags from a collection of web pages in python

我正在尝试从包含 html 文档集合的 .gz 文件中检索内容,它是来自 GOV2 集合的文件。每个页面由标签分隔,每个标签包含多个元信息,其中包括文档的 ID 和(或)其内容。 这是此类文件的示例:

<doc>
<docno>GX000-xx-xxxxxxx</docno>
<dochdr>
<!-- no relevant meta info -->
</dochdr>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN">

<html>
<!-- the content I want to extract -->
</html>
</doc>
<doc>
<docno>GX000-xx-xxxxxxy</docno>
<dochdr>
<!-- no relevant meta info -->
</dochdr>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN">

<html>
<!-- another content I want to extract -->
</html>
</doc>

我需要一个列表,分别包含每个 docno 和 html 标签的每个内容。

这是我使用 BeautifulSoup 所做的:

doc_file = 'xx.gz'
f = gzip.open(data_dir + doc_file)
doc_string = f.read()
f.close()

soup = BeautifulSoup(doc_string, "html.parser")
doc_list = soup.select('DOC')

doc_no = []
doc_content = []
for doc in doc_list:
    doc_no.append(doc.find('docno').get_text())
    doc_raw = doc.find('html')
    if doc_raw is None: #It's possible a doc has no html tag
        doc_content.append('<null/>')
    else:
        doc_content.append(re.sub(r'(\n\s*)+\n+', '\n', doc.find('html').get_text()))

这行得通,但是 html.parser 是一个非常慢的解析器(每个文件大约 4 分钟,但我有几千个要从中提取...)。值得庆幸的是,使用另一个像 lxml 这样的解析器几乎是即时的。但是,无论出于何种原因,这样的解析器都会删除 <html> 标记。我尝试了另一种方法,在调用 BeautifulSoup 之前,我在 doc_string 中替换了这些标签(使用 doc_string=doc_string.replace(b'<html>', b'<2html>')但是:

你有更快的方法来完成这样的任务吗?

感谢您的帮助。

正如我在 post 中所说,我认为将文档转换为字符串,然后替换 html 标签,然后将字符串重新编码为字节会太长。原来我错了

我在弄清楚这一点后使用的策略是用另一个唯一的词(如下文中的 htmltag 替换每个 html 出现(不仅是标签)。然后,一旦我 删除了 htmltag 的内容,我将每个剩余的 htmltag 替换回 html。这样内容就完全没有改变了。

f = gzip.open(data_dir + doc_file)
doc_string = f.read()
f.close()

doc_string_str = doc_string.decode(errors='ignore')
doc_string_str = doc_string_str.replace('html', 'htmltag')
doc_string = doc_string_str.encode()

soup = BeautifulSoup(doc_string, "lxml")
doc_list = soup.select('DOC')

doc_no = []
doc_content = []
for doc in doc_list:
    doc_no.append(doc.find('docno').get_text())
    doc_raw = doc.find('htmltag')
    if doc_raw is None: #It's possible a doc has no html tag
        doc_content.append('<null/>')
    else:
        doc_content.append(re.sub(r'(\n\s*)+\n+', '\n', doc.find('htmltag').get_text()).replace('htmltag', 'html'))

感谢@shellter 和@JL_Peyret 的帮助,我基本上是按照你告诉我的,但直接在 Python 中。它知道每个文档大约需要 15 秒。