我想使用Python从HTML文件中提取文本。我想从本质上得到相同的输出,如果我从浏览器复制文本,并将其粘贴到记事本。
我想要一些更健壮的东西,而不是使用正则表达式,正则表达式可能会在格式不佳的HTML上失败。我见过很多人推荐Beautiful Soup,但我在使用它时遇到了一些问题。首先,它会抓取不需要的文本,比如JavaScript源代码。此外,它也不解释HTML实体。例如,我会期望'在HTML源代码中转换为文本中的撇号,就像我将浏览器内容粘贴到记事本一样。
更新html2text看起来很有希望。它正确地处理HTML实体,而忽略JavaScript。然而,它并不完全生成纯文本;它产生的降价,然后必须转换成纯文本。它没有示例或文档,但代码看起来很干净。
相关问题:
在python中过滤HTML标签并解析实体
在Python中将XML/HTML实体转换为Unicode字符串
这不是一个完全的Python解决方案,但它会将Javascript生成的文本转换为文本,我认为这是重要的(例如google.com)。浏览器Links(不是Lynx)有一个Javascript引擎,可以通过-dump选项将源代码转换为文本。
所以你可以这样做:
fname = os.tmpnam()
fname.write(html_source)
proc = subprocess.Popen(['links', '-dump', fname],
stdout=subprocess.PIPE,
stderr=open('/dev/null','w'))
text = proc.stdout.read()
而不是HTMLParser模块,签出htmllib。它有一个类似的界面,但是为您做了更多的工作。(它非常古老,所以在摆脱javascript和css方面没有多大帮助。你可以创建一个派生类,但是可以添加start_script和end_style这样的方法(详见python文档),但对于格式不正确的html来说,很难可靠地做到这一点。)不管怎样,这里有一些简单的东西,它将纯文本打印到控制台
from htmllib import HTMLParser, HTMLParseError
from formatter import AbstractFormatter, DumbWriter
p = HTMLParser(AbstractFormatter(DumbWriter()))
try: p.feed('hello<br>there'); p.close() #calling close is not usually needed, but let's play it safe
except HTMLParseError: print ':(' #the html is badly malformed (or you found a bug)
我发现的最好的一段代码提取文本没有javascript或不想要的东西:
from urllib.request import urlopen
from bs4 import BeautifulSoup
url = "http://news.bbc.co.uk/2/hi/health/2284783.stm"
html = urlopen(url).read()
soup = BeautifulSoup(html, features="html.parser")
# kill all script and style elements
for script in soup(["script", "style"]):
script.extract() # rip it out
# get text
text = soup.get_text()
# break into lines and remove leading and trailing space on each
lines = (line.strip() for line in text.splitlines())
# break multi-headlines into a line each
chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
# drop blank lines
text = '\n'.join(chunk for chunk in chunks if chunk)
print(text)
你只需要安装BeautifulSoup:
pip install beautifulsoup4
Beautiful soup可以转换html实体。考虑到HTML经常有bug并且充满unicode和HTML编码问题,这可能是您最好的选择。这是我用来将html转换为原始文本的代码:
import BeautifulSoup
def getsoup(data, to_unicode=False):
data = data.replace(" ", " ")
# Fixes for bad markup I've seen in the wild. Remove if not applicable.
masssage_bad_comments = [
(re.compile('<!-([^-])'), lambda match: '<!--' + match.group(1)),
(re.compile('<!WWWAnswer T[=\w\d\s]*>'), lambda match: '<!--' + match.group(0) + '-->'),
]
myNewMassage = copy.copy(BeautifulSoup.BeautifulSoup.MARKUP_MASSAGE)
myNewMassage.extend(masssage_bad_comments)
return BeautifulSoup.BeautifulSoup(data, markupMassage=myNewMassage,
convertEntities=BeautifulSoup.BeautifulSoup.ALL_ENTITIES
if to_unicode else None)
remove_html = lambda c: getsoup(c, to_unicode=True).getText(separator=u' ') if c else ""