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

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

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


相关问题:

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


当前回答

有用于数据挖掘的模式库。

http://www.clips.ua.ac.be/pages/pattern-web

你甚至可以决定保留什么标签:

s = URL('http://www.clips.ua.ac.be').download()
s = plaintext(s, keep={'h1':[], 'h2':[], 'strong':[], 'a':['href']})
print s

其他回答

安装html2text using

PIP安装html2text

然后,

>>> import html2text
>>>
>>> h = html2text.HTML2Text()
>>> # Ignore converting links from HTML
>>> h.ignore_links = True
>>> print h.handle("<p>Hello, <a href='http://earth.google.com/'>world</a>!")
Hello, world!

我知道这里已经有很多答案了,但我认为newspaper3k也值得一提。我最近需要完成一个类似的任务,即从网络上的文章中提取文本,到目前为止,这个库在我的测试中完成了出色的工作。它忽略菜单项和边栏中的文本,以及OP请求时出现在页面上的任何JavaScript。

from newspaper import Article

article = Article(url)
article.download()
article.parse()
article.text

如果你已经下载了HTML文件,你可以这样做:

article = Article('')
article.set_html(html)
article.parse()
article.text

它甚至有一些NLP功能来总结文章的主题:

article.nlp()
article.summary

这里的所有方法在一些网站上都不能很好地工作。由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代码加载它的东西),但至少我们不需要疯狂的复制/粘贴,这阻碍了我们在共享剪贴板的机器上运行多个脚本。

虽然很多人提到使用regex来剥离html标记,但它有很多缺点。

例如:

<p>hello&nbsp;world</p>I love you

应该解析为:

Hello world
I love you

这是我想到的一个片段,你可以根据你的特定需求定制它,它就像一个魅力

import re
import html
def html2text(htm):
    ret = html.unescape(htm)
    ret = ret.translate({
        8209: ord('-'),
        8220: ord('"'),
        8221: ord('"'),
        160: ord(' '),
    })
    ret = re.sub(r"\s", " ", ret, flags = re.MULTILINE)
    ret = re.sub("<br>|<br />|</p>|</div>|</h\d>", "\n", ret, flags = re.IGNORECASE)
    ret = re.sub('<.*?>', ' ', ret, flags=re.DOTALL)
    ret = re.sub(r"  +", " ", ret)
    return ret

对我来说最好的工作是铭文。

https://github.com/weblyzard/inscriptis

import urllib.request
from inscriptis import get_text

url = "http://www.informationscience.ch"
html = urllib.request.urlopen(url).read().decode('utf-8')

text = get_text(html)
print(text)

结果真的很好