从 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>'
)但是:
进程很慢
出于某种原因,<
被转换为 <
,要取消转义,我发现没有比解码 doc_string
,取消转义,然后重新转义更简单的方法了对其进行编码,这在时间上是荒谬的。即使直接替换每个 b'2html'
b'html'
似乎也逃避了 <
和 >
你有更快的方法来完成这样的任务吗?
感谢您的帮助。
正如我在 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 秒。
我正在尝试从包含 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>'
)但是:
进程很慢
出于某种原因,
<
被转换为<
,要取消转义,我发现没有比解码doc_string
,取消转义,然后重新转义更简单的方法了对其进行编码,这在时间上是荒谬的。即使直接替换每个b'2html'
b'html'
似乎也逃避了<
和>
你有更快的方法来完成这样的任务吗?
感谢您的帮助。
正如我在 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 秒。