【问题标题】:p tags are not removed in for loop with BeautifulSoup使用 BeautifulSoup 在 for 循环中不会删除 p 标签
【发布时间】:2020-10-24 00:15:30
【问题描述】:

我正在尝试从文本中删除一些标记,例如 <p>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n</p><p>\r\n</p>

这是我在这里使用 BeautifulSoup 的代码。

        article = Article.objects.all()

        for obj in article:
            soup_en = BeautifulSoup(obj.text_en, features="html5lib")
            obj.text_en = '\n'.join(map(str, OrderedSet(soup_en.find_all('p')))).replace(r'\r\n', '').replace('#####444#####', '').replace('#####555#####', '').replace('<p></p>', '').replace(r'<p>&nbsp;</p>', '')
            obj.save()

带有要删除标记的文本:

<p>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n</p>

<p>\r\n</p>

<p>Name of person </p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>\r\n</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>\r\n</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>

当我只处理一个对象时一切正常,例如obj = Article.objects.get(old_id=50) 但是当我将代码放入for循环时,我在文本中发现奇怪的结果,我的意思是有些部分是双倍的(&lt;p&gt;Name of person &lt;/p&gt;),并且在文本的开头是标记

<p>&nbsp;</p>

<p>Name of person </p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>Name of person </p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>

【问题讨论】:

  • 试试代码text = re.sub(r'&lt;p&gt;[\r\n\s]*&lt;/p&gt;','',text )
  • 您应该在 bs 找到的每个元素上调用 .text(),这只会为您提供文本并删除任何 HTML 元素。
  • 您能否告诉我们obj.text_en 的外观以及您期望它之后的外观?

标签: python django regex beautifulsoup tags


【解决方案1】:

我假设obj.text_en 看起来像-

<p>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n</p>

<p>&nbsp;</p>

<p>\r\n</p>

<p>#####444#####</p>

<p>#####555#####</p>

<p>Name of person </p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>\r\n</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>\r\n</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>

这应该涵盖您似乎试图替换的所有情况。

现在,像 CRLF 和 &amp;nbsp; 这样的东西可以通过在每个元素的 .text 上执行 strip 轻松摆脱。

####444#### 之类的东西最好用正则表达式处理。

因此,如果我们有这样的 html-

html = """<p>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n</p>

<p>&nbsp;</p>

<p>\r\n</p>

<p>#####444#####</p>

<p>#####555#####</p>

<p>Name of person </p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>\r\n</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>\r\n</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>"""

这是你需要的-

import re
from bs4 import BeautifulSoup

...

soup = BeautifulSoup(html, 'html5lib')
# The following regex matches either empty strings (`''`) or patterns such as `#####555#####`
BAD_PATTERN = re.compile(r'^(?:|#{5}\d{3}#{5})$')
paras = soup.find_all('p')
# Join all the "good" strings with a newline
content = '\n'.join([item for item in map(lambda x: x.text.strip(), paras) if not BAD_PATTERN.match(item)])
print(content)

输出-

人名

Lorem ipsum dolor sit amet,consectetur adipiscing elit,sed do eiusmod tempor incididunt ut labore et dolore magna aliqua。 Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat。 Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur。 Exceptioneur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum。

Lorem ipsum dolor sit amet,consectetur adipiscing elit,sed do eiusmod tempor incididunt ut labore et dolore magna aliqua。 Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat。 Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur。 Exceptioneur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum。

Lorem ipsum dolor sit amet,consectetur adipiscing elit,sed do eiusmod tempor incididunt ut labore et dolore magna aliqua。

它做了什么,它是如何做的-

  • 首先,这个正则表达式 ^(?:|#{5}\d{3}#{5})$ - 将匹配空字符串 ('') 或像 #####555##### 这样的模式。即 5 个标签,后跟 3 个数字,然后是 5 个标签。

    查看demo

  • map(lambda x: x.text.strip(), paras) 将返回一个地图对象,其中每个元素只是每个 p 元素的文本,去掉了空白字符。

  • 然后我们遍历 map 并创建一个列表,其中仅包含与前面提到的模式不匹配的文本

    [item for item in map(lambda x: x.text.strip(), paras) if not BAD_PATTERN.match(item)]

  • 最后,我们用\n 加入上述列表的内容。

【讨论】:

    猜你喜欢
    • 2020-10-27
    • 2014-10-02
    • 1970-01-01
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    • 2022-07-30
    • 1970-01-01
    相关资源
    最近更新 更多