使BeautifulSoup像浏览器一样处理换行符

时间:2015-05-19 22:57:14

标签: python html beautifulsoup

我正在使用BeautifulSoup(版本'4.3.2'与Python 3.4)将html文档转换为文本。我遇到的问题是,有时网页的换行符“\ n”实际上不会在浏览器中呈现为新行,但是当BeautifulSoup将它们转换为文本时,它会留在“\ n”中。

示例:

您的浏览器可能会在一行中呈现以下所有内容(即使中间有换行符):

这是一个 段落。

您的浏览器可能会在多行中呈现以下内容,即使我输入的内容没有新行:

这是一个段落。

这是另一段。

但是当BeautifulSoup将相同的字符串转换为文本时,它使用的唯一换行符是换行符文字 - 它总是使用它们:

from bs4 import BeautifulSoup

doc = "<p>This is a\nparagraph.</p>"
soup = BeautifulSoup(doc)

soup.text
Out[181]: 'This is a \n paragraph.'

doc = "<p>This is a paragraph.</p><p>This is another paragraph.</p>"
soup = BeautifulSoup(doc)

soup.text
Out[187]: 'This is a paragraph.This is another paragraph.'

有谁知道如何以更漂亮的方式制作BeautifulSoup提取文本(或者真的只是让所有换行符正确)?还有其他简单的解决方法吗?

3 个答案:

答案 0 :(得分:6)

get_text可能会对您有所帮助:

>>> from bs4 import BeautifulSoup
>>> doc = "<p>This is a paragraph.</p><p>This is another paragraph.</p>"
>>> soup = BeautifulSoup(doc)
>>> soup.get_text(separator="\n")
u'This is a paragraph.\nThis is another paragraph.'

答案 1 :(得分:1)

虽然我确实意识到这是一篇旧帖子,但我想突出显示 bs4 中从标签打印文本的方式中的一些行为。

我不是 html 专家,但这些是我在尝试像浏览器那样制作 bs4 打印文本时考虑的几件事 -

我将要描述的行为适用于 BeautifulSoup 中的 tag.get_text()tag.find_all(text=True,recursive=True) 功能< /p>

1) HTML 源代码中的新行

如果 html 源代码中可用,Beautiful soup 会打印一个新行

2) 由于块级元素而隐式换行

如果标签周围没有源新行,Beautiful Soup 不会在块元素之前和之后添加新行,例如 'p'

3)
标签

如果源代码包含
标记并且
标记周围没有源代码新行,BeautifulSoup 不会打印新行

解决方案

这是一个适用于许多情况的解决方案(限制因素是 -1)所有内联元素的列表 2)CSS/JS 如何在浏览器环境中影响运行时的内联性或块性

def get_text(tag:bs4.Tag) -> str:
    _inline_elements = {"a","span","em","strong","u","i","font","mark","label","s","sub","sup","tt","bdo","button","cite","del","b","a","font"}

    def _get_text(tag:bs4.Tag) -> Generator:
     
        for child in tag.children:
            if type(child) is Tag:
                # if the tag is a block type tag then yield new lines before after
                is_block_element = child.name not in _inline_elements
                if is_block_element: yield "\n"
                yield from ["\n"] if child.name=="br" else  _get_text(child)
                if is_block_element: yield "\n"
            elif type(child) is NavigableString:
                yield child.string
     return "".join(_get_text(tag))

答案 2 :(得分:0)

我会看一下 python-markdownify 。它以标记格式将html变成非常易读的文本。

可在pypi获得:https://pypi.python.org/pypi/markdownify/0.4.0

和github:https://github.com/matthewwithanm/python-markdownify