BeautifulSoup中的.descendants似乎不按预期工作

1 投票
1 回答
1475 浏览
提问于 2025-04-18 03:49

我正在尝试用 .replaceWith 方法替换一个长网页中的一些元素(类名为 method)。为此,我使用 .descendants 方法来遍历这些元素,检查 dl 元素是否是我想要的。但是,这个方法只对相邻的 0 到 2 个元素有效。每当遇到第 3 个及之后的元素时,它们就会被“忽略”。如果我执行同样的代码两次,结果会是连续替换掉 4 个 dl 元素,依此类推。

for elem in matches:
 for child in elem.descendants:
    if not isinstance(child, NavigableString) and child.dl is not None  and 'method' in child.dl.get('class'):
         text = "<p>***removed something here***</p>"
         child.dl.replaceWith(BeautifulSoup(text))

这个(非常傻的)解决办法是找到连续的 dl 元素的最大数量,然后把这个数字除以二,执行那么多次。我希望能找到一个聪明(而且快速)的解决方案,并且(更重要的是)理解这里出了什么问题。

补充说明:用于测试的网页是这个:https://docs.python.org/3/library/stdtypes.html,错误可以在第 4.7.1 节的字符串方法中看到(那里有很多可用的方法)。

补充说明 2:但我并不是只使用这个网页,而是使用它的部分内容。这些 HTML 部分存储在一个列表中,我只想在它们不是第一个 HTML 元素时“移除” dl 元素(也就是说,如果它是头部元素,我想保留它)。

总的来说,我的代码现在是这样的:

from bs4 import BeautifulSoup, NavigableString

soup = BeautifulSoup(open("/home/sven/Bachelorarbeit/python-doc-extractor-for-cado/extractor-application/index.html"))
f = open('test.html','w')    #needs to exist
f.truncate
matches=[]

dl_elems = soup.find_all(['dl'], attrs={'class': ['class', 'method','function','describe', 'classmethod', 'staticmethod']})   # grab all possible dl-elements

sections = soup.find_all(['div'], attrs = {'class':'section'})   #grab all section-elements

matches = dl_elems + sections   #merge the lists to get all results

for elem in matches:
  for child in elem.descendants:
      if not isinstance(child, NavigableString) and child.dl is not None  and 'method' in child.dl.get('class'):
           text = "<p>***removed something here***</p>"
           child.dl.replaceWith(BeautifulSoup(text))


print(matches,file=f)
f.close()

1 个回答

1

这个想法是找到所有带有 class="method"dl 元素,然后把它们替换成 p 标签:

import urllib2
from bs4 import BeautifulSoup, Tag

# get the html
url = "https://docs.python.org/3/library/stdtypes.html"
soup = BeautifulSoup(urllib2.urlopen(url))

# replace all `dl` elements with `method` class
for elem in soup('dl', class_='method'):
    tag = Tag(name='p')
    tag.string = '***removed something here***'
    elem.replace_with(tag)

print soup.prettify()

更新(根据问题的修改进行了调整):

dl_elems = soup.find_all(['dl'], attrs={'class': ['class', 'method','function','describe', 'classmethod', 'staticmethod']})   # grab all possible dl-elements
sections = soup.find_all(['div'], attrs={'class': 'section'})   #grab all section-elements

for parent in dl_elems + sections:
    for elem in parent.find_all('dl', {'class': 'method'}):
        tag = Tag(name='p')
        tag.string = '***removed something here***'
        elem.replace_with(tag)

print dl_elems + sections

撰写回答