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

问题描述 投票:4回答:1

我试图从一个包含html文档集合的.gz文件中检索内容,这是一个来自GOV2集合的文件,每个页面由标签分隔,每个标签包含几个元信息,其中包括文档的id和(或),其内容。每个页面由标签分开,每个标签包含几个元信息,其中包括文档的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> 标签。我尝试了另一种方法,在 doc_string 中替换了这些标签(使用 doc_string=doc_string.replace(b'<html>', b'<2html>')才调用BeautifulSoup,但。

  • 这个过程很慢

  • 不知为何 < 变成了 &lt;要解开它,我发现没有比解码更简单的方法了。doc_string,解开它,然后重新编码,这在时间上是荒谬的。即使直接替换 b'html'b'2html' 似乎逃不过 <>

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

谢谢你的帮助,我想从一个包含html文档集合的.gz文件中检索内容,这是一个GOV2集合的文件。

python html web-scraping beautifulsoup xmlstarlet
1个回答
1
投票

正如我在帖子中所说的,我认为将文档转换为字符串,然后替换为 html 标签,然后再将字符串重新编码为字节就太长了。事实证明我错了。

在搞清楚这个问题后,我采用的策略是把每一个的 html 由另一个独特的词出现(不仅是标签)(比如下面的与 htmltag). 然后有一次,我把一个的内容废掉了。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秒。

© www.soinside.com 2019 - 2024. All rights reserved.