BeautifulSoup抓住可见的网页文本

use*_*864 115 python text beautifulsoup html-content-extraction

基本上,我想使用BeautifulSoup严格抓取网页上的可见文字.例如,这个网页是我的测试用例.而且我主要想在这里和那里获得正文(文章)甚至几个标签名称.我在这个SO问题中尝试过这个建议,它返回了许多<script>我不想要的标签和HTML注释.我无法找出函数所需的参数findAll(),以便在网页上获取可见文本.

那么,我应该如何找到除脚本,评论,CSS等之外的所有可见文本?

jbo*_*chi 211

试试这个:

from bs4 import BeautifulSoup
from bs4.element import Comment
import urllib.request


def tag_visible(element):
    if element.parent.name in ['style', 'script', 'head', 'title', 'meta', '[document]']:
        return False
    if isinstance(element, Comment):
        return False
    return True


def text_from_html(body):
    soup = BeautifulSoup(body, 'html.parser')
    texts = soup.findAll(text=True)
    visible_texts = filter(tag_visible, texts)  
    return u" ".join(t.strip() for t in visible_texts)

html = urllib.request.urlopen('http://www.nytimes.com/2009/12/21/us/21storm.html').read()
print(text_from_html(html))
Run Code Online (Sandbox Code Playgroud)

  • `soup.findAll(text = True)的+1从不知道该功能 (39认同)
  • 在可见函数中,用于查找注释的elif似乎不起作用.我不得不将它更新为`elif isinstance(element,bs4.element.Comment):`.我还在父母名单中添加了'meta'. (11认同)
  • 对于最近的BS4(至少),您可以使用`isinstance(element,Comment)`来识别注释,而不是与正则表达式匹配. (7认同)
  • 我相信第2行应该是````汤= BeautifulSoup(html)```` (5认同)
  • 上面的过滤器在结果中有很多\n,添加以下代码以消除空格和新行:`elif re.match(r"[\ s\r \n] +",str(element)):返回False (3认同)

nmg*_*eek 34

来自@jbochi的批准答案对我不起作用.str()函数调用引发异常,因为它无法编码BeautifulSoup元素中的非ascii字符.以下是将示例网页过滤为可见文本的更简洁方法.

html = open('21storm.html').read()
soup = BeautifulSoup(html)
[s.extract() for s in soup(['style', 'script', '[document]', 'head', 'title'])]
visible_text = soup.getText()
Run Code Online (Sandbox Code Playgroud)


bum*_*kin 30

import urllib
from bs4 import BeautifulSoup

url = "https://www.yahoo.com"
html = urllib.urlopen(url).read()
soup = BeautifulSoup(html)

# 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.encode('utf-8'))
Run Code Online (Sandbox Code Playgroud)

  • 以前的答案对我不起作用,但这确实:) (4认同)

Pau*_*aul 10

我完全尊重使用Beautiful Soup来获取渲染内容,但它可能不是获取页面上渲染内容的理想包.

我有一个类似的问题,以获得渲染内容,或在典型的浏览器中的可见内容.特别是我有许多非典型案例可以使用下面这么简单的例子.在这种情况下,不可显示的标记嵌套在样式标记中,并且在我检查过的许多浏览器中都不可见.存在其他变体,例如将类标签设置显示为无.然后使用这个类作为div.

<html>
  <title>  Title here</title>

  <body>

    lots of text here <p> <br>
    <h1> even headings </h1>

    <style type="text/css"> 
        <div > this will not be visible </div> 
    </style>


  </body>

</html>
Run Code Online (Sandbox Code Playgroud)

上面发布的一个解决方案是

html = Utilities.ReadFile('simple.html')
soup = BeautifulSoup.BeautifulSoup(html)
texts = soup.findAll(text=True)
visible_texts = filter(visible, texts)
print(visible_texts)


[u'\n', u'\n', u'\n\n        lots of text here ', u' ', u'\n', u' even headings ', u'\n', u' this will not be visible ', u'\n', u'\n']
Run Code Online (Sandbox Code Playgroud)

这个解决方案在许多情况下肯定有应用程序,并且通常做得很好但是在上面发布的html中它保留了未呈现的文本.在搜索了SO之后,一些解决方案出现在这里BeautifulSoup get_text没有删除所有标签和JavaScript, 并且在这里使用Python将HTML呈现为纯文本

我尝试了这两种解决方案:html2text和nltk.clean_html,并对计时结果感到惊讶,所以认为他们应该为子孙后代做出回答.当然,速度很大程度上取决于数据的内容......

@Helge的一个答案是关于使用所有东西的nltk.

import nltk

%timeit nltk.clean_html(html)
was returning 153 us per loop
Run Code Online (Sandbox Code Playgroud)

返回带有渲染html的字符串非常有效.这个nltk模块甚至比html2text更快,尽管html2text可能更强大.

betterHTML = html.decode(errors='ignore')
%timeit html2text.html2text(betterHTML)
%3.09 ms per loop
Run Code Online (Sandbox Code Playgroud)

  • 对于将来查看此答案的任何人,clean_html 已被 NLTK 删除:/sf/ask/1820145351/ (2认同)

Die*_*rez 6

使用 BeautifulSoup 最简单的方法,用更少的代码来获取字符串,没有空行和废话。

tag = <Parent_Tag_that_contains_the_data>
soup = BeautifulSoup(tag, 'html.parser')

for i in soup.stripped_strings:
    print repr(i)
Run Code Online (Sandbox Code Playgroud)