我想使用Python从HTML文件中提取文本。我想从本质上得到相同的输出,如果我从浏览器复制文本,并将其粘贴到记事本。

我想要一些更健壮的东西,而不是使用正则表达式,正则表达式可能会在格式不佳的HTML上失败。我见过很多人推荐Beautiful Soup,但我在使用它时遇到了一些问题。首先,它会抓取不需要的文本,比如JavaScript源代码。此外,它也不解释HTML实体。例如,我会期望'在HTML源代码中转换为文本中的撇号,就像我将浏览器内容粘贴到记事本一样。

更新html2text看起来很有希望。它正确地处理HTML实体,而忽略JavaScript。然而,它并不完全生成纯文本;它产生的降价,然后必须转换成纯文本。它没有示例或文档,但代码看起来很干净。


相关问题:

在python中过滤HTML标签并解析实体 在Python中将XML/HTML实体转换为Unicode字符串


当前回答

如果你想从网页中自动提取文本段落,有一些可用的python包,如Trafilatura。作为基准测试的一部分,比较了几个python包:

https://github.com/adbar/trafilatura#evaluation-and-alternatives

html_text https://github.com/TeamHG-Memex/html-text inscriptis https://github.com/weblyzard/inscriptis newspaper3k justext boilerpy3 https://github.com/jmriebold/BoilerPy3 基线 goose3 https://github.com/goose3/goose3 readability-lxml https://github.com/predatell/python-readability-lxml news-please https://github.com/fhamborg/news-please readabilipy https://github.com/alan-turing-institute/ReadabiliPy trafilatura

其他回答

注意:NTLK不再支持clean_html函数

下面是原始答案,评论部分有备选答案。


使用NLTK

我浪费了4-5个小时来修复html2text的问题。幸运的是我遇到了NLTK。 它神奇地起作用。

import nltk   
from urllib import urlopen

url = "http://news.bbc.co.uk/2/hi/health/2284783.stm"    
html = urlopen(url).read()    
raw = nltk.clean_html(html)  
print(raw)

这里的所有方法在一些网站上都不能很好地工作。由JS代码生成的段落可以抵抗上述所有问题。这是我最终得到的启发,受到这个和这个的启发。

这个想法是在webdriver中加载页面,并滚动到页面的末尾,让JS做它的事情来生成/加载页面的其余部分。然后插入键击命令选择全部复制/粘贴整个页面:

import selenium
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import pyperclip
import time

driver = webdriver.Chrome()
driver.get("https://www.lazada.com.ph/products/nike-womens-revolution-5-running-shoes-black-i1262506154-s4552606107.html?spm=a2o4l.seller.list.3.6f5d7b6cHO8G2Y&mp=1&freeshipping=1")

# Scroll down to end of the page to let all javascript code load its content
lenOfPage = driver.execute_script("window.scrollTo(0, document.body.scrollHeight);var lenOfPage=document.body.scrollHeight;return lenOfPage;")
match=False
while(match==False):
        lastCount = lenOfPage
        time.sleep(1)
        lenOfPage = driver.execute_script("window.scrollTo(0, document.body.scrollHeight);var lenOfPage=document.body.scrollHeight;return lenOfPage;")
        if lastCount==lenOfPage:
            match=True

# copy from the webpage
element = driver.find_element_by_tag_name('body')
element.send_keys(Keys.CONTROL,'a')
element.send_keys(Keys.CONTROL,'c')
alltext = pyperclip.paste()
alltext = alltext.replace("\n", " ").replace("\r", " ")  # cleaning the copied text
print(alltext )

它很慢。但其他的都不奏效。

更新:一个更好的方法是在滚动到页面末尾后使用inscriptis库加载页面的源代码:

from inscriptis import get_text
text = get_text(driver.page_source)

仍然不能与无头驱动程序一起工作(页面检测到它不是由real显示,滚动到末尾不会使JS代码加载它的东西),但至少我们不需要疯狂的复制/粘贴,这阻碍了我们在共享剪贴板的机器上运行多个脚本。

这不是一个完全的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()

你也可以在stripogram库中使用html2text方法。

from stripogram import html2text
text = html2text(your_html_string)

需要安装stripogram,请执行sudo easy_install stripogram命令

在Python 3中。X,你可以通过导入“imaplib”和“电子邮件”包,以非常简单的方式做到这一点。虽然这是一个老帖子,但也许我的答案可以帮助到这个帖子的新人。

status, data = self.imap.fetch(num, '(RFC822)')
email_msg = email.message_from_bytes(data[0][1]) 
#email.message_from_string(data[0][1])

#If message is multi part we only want the text version of the body, this walks the message and gets the body.

if email_msg.is_multipart():
    for part in email_msg.walk():       
        if part.get_content_type() == "text/plain":
            body = part.get_payload(decode=True) #to control automatic email-style MIME decoding (e.g., Base64, uuencode, quoted-printable)
            body = body.decode()
        elif part.get_content_type() == "text/html":
            continue

现在你可以打印主体变量,它将是明文格式:)如果它对你来说足够好,那么它将很好地选择它作为接受的答案。