我目前有两个函数从Python中提取HTML <body>
文本并将其作为一个单词包返回。它们提供相同的输出。我还清理了各种标签,否则会给我垃圾文本(例如<script>
代码)。
def html_to_bow_bs(text):
if text is None or len(text)==0:
return []
soup = BeautifulSoup(text, "lxml",parse_only=SoupStrainer('body'))
# Remove all irrelevant tags
for elem in soup.findAll(['script','style','a']):
elem.extract()
body_text = soup.findAll("body")
if len(body_text) == 0:
return []
# Encoding. Remove extra whitespace and unprintable characters
the_text = body_text[0].get_text().encode('utf-8')
the_text = str(the_text)
the_text = the_text.strip()
the_text = re.sub(r'[^\x00-\x7F]+',' ',the_text)
return [w.lower() for w in the_text.split()]
def html_to_bow_bs_lxml(text):
if text is None or len(text)==0:
return []
body_re = re.findall('<body(.*?)</body>', text, flags=re.DOTALL)
if len(body_re) == 0:
return []
fragment = body_re[0]
# Remove irrelevant tags
fragment = re.sub(r'<script.*?</script>', ' ', fragment, flags=re.DOTALL)
fragment = re.sub(r'<style.*?</style>', ' ', fragment, flags=re.DOTALL)
text = "<body" + fragment + "</body>"
soup = BeautifulSoup(text, "lxml")
if soup is None:
return []
# Remote more irrelevant tags
for elem in soup.findAll(['a']):
elem.extract()
# Encoding. Remove extra whitespace and unprintable characters
the_text = body_text[0].get_text().encode('utf-8')
the_text = str(the_text)
the_text = the_text.strip()
the_text = re.sub(r'[^\x00-\x7F]+',' ',the_text)
return [w.lower() for w in the_text.split()]
我的主要要求是匹配输出:来自html_to_bow_bs_lxml(text)
的单词集与html_to_bow_bs(text)
匹配。目前,两者的运行时间都相同;对于330页,它们运行大约20秒(慢!)。如果我用正则表达式删除并替换我的第二个函数中的最后一个soup.findAll(['a'])...extract()
,我可以减少6秒的时间。将BeautifulSoup
完全替换为lxml.etree
可以再削减10秒,使总运行时间约为3-4秒。但是,当用正则表达式替换时,
BeautifulSoup
时输出不匹配或我已经看到了通常在StackOverflow上使用Python提取HTML的各种建议,但这些建议可追溯到几年前(例如2012年)。从那时起,对图书馆进行了许多更新,这是可以理解的。
(我也尝试过pyquery,但它并不总是正确地提取身体。)
答案 0 :(得分:1)
你已经做了很多事情来加快速度 - 汤过滤器和lxml
解析器通常是在使用BeautifulSoup
优化解析时首先尝试的。
以下是对此特定代码的一些改进。
删除身体存在检查:
body_text = soup.findAll("body")
if len(body_text) == 0:
return []
并改为使用find()
。
将if text is None or len(text)==0:
替换为if not text:
。
通过get_text(strip=True)
剥离。
改进的代码:
def html_to_bow_bs(text):
if not text:
return []
soup = BeautifulSoup(text, "lxml", parse_only=SoupStrainer('body'))
# Remove all irrelevant tags
for elem in soup.find_all(['script','style','a']):
elem.extract()
body = soup.find("body")
if not body:
return []
the_text = body.get_text(strip=True).encode('utf-8')
the_text = re.sub(r'[^\x00-\x7F]+', ' ', the_text)
return [w.lower() for w in the_text.split()]
这些只是微观改进,我认为它们不会改变整体表现。我还会研究:
pypy
运行脚本(beautifulsoup4
为compatible,但您无法使用lxml
解析器 - 请使用html.parser
或{ {1}})。如果没有修改代码,你可能会赢得很多。答案 1 :(得分:0)
使用requests module和bs4
这是打印正文的最简单方法。
import requests
from bs4 import BeautifulSoup
url = "yourUrl"
r = requests.get(url)
soup = BeautifulSoup(r.content, 'lxml')
items = soup.find_all('body')
for item in items:
print item.text
注意:如果你打印所有正文,它也会打印jquery和javascript函数,以防万一。