使用Beautiful Soup仅按<br>标签拆分段落,stripped_strings无法满足需求的解决方案
使用Beautiful Soup仅按
标签拆分段落,stripped_strings无法满足需求的解决方案
标签拆分段落,stripped_strings无法满足需求的解决方案
嘿,我完全懂你的困扰——stripped_strings虽然方便,但它会把所有独立的文本节点拆分开,哪怕这些文本属于同一个<br>分段里的不同子标签(比如你例子里的<font>和后面的COAT),所以才会出现RT和COAT被分成两行的情况。咱们要做的是把<br>作为唯一分隔符,把每个<br>之间的所有文本(不管嵌套在什么子标签里)合并成完整的一行。
下面给你两种可行的解决方案,你可以根据自己的HTML结构选更合适的:
方法一:直接遍历节点,按<br>分组合并文本
这种方法适合HTML结构稍复杂的场景,能精准控制每个分段的文本合并:
from bs4 import BeautifulSoup import requests pages = ['https://terminology.collectionstrust.org.uk/British-Museum-objects/Obthesa1.htm'] b = 1 for bp in pages: response = requests.get(bp) html = response.text soup = BeautifulSoup(html, "lxml") for blockquote in soup.find_all('blockquote'): # 获取当前blockquote对应的前置p标签文本 prev_p = blockquote.find_previous('p') prev_text = prev_p.text.strip() if prev_p else "" # 定位到blockquote里的内容容器p标签 p_container = blockquote.find('p') if not p_container: continue current_line = [] # 遍历p标签下的所有子节点 for node in p_container.contents: # 遇到<br>就结束当前行,输出合并后的文本 if node.name == 'br': if current_line: line_text = ''.join(current_line).strip() if line_text: print(b, prev_text, line_text) current_line = [] else: # 非<br>节点,提取所有文本(包括子标签里的)加入当前行 node_text = node.get_text(strip=True) if node_text: current_line.append(node_text) # 处理最后一个分段(可能没有<br>结尾) if current_line: line_text = ''.join(current_line).strip() if line_text: print(b, prev_text, line_text) b += 1
代码说明:
- 不再依赖
stripped_strings遍历所有文本,而是直接遍历<p>标签的子节点。 - 遇到
<br>就把之前收集的所有文本拼接成一行,输出后重置收集容器。 - 对于非
<br>的节点,用get_text(strip=True)提取它包含的所有文本(不管嵌套多少层子标签),加入当前行的收集列表。
方法二:替换<br>为换行符,再拆分文本
如果你的HTML结构比较规范(所有<br>都是直接放在<p>下,没有嵌套在其他标签里),这种方法更简洁:
from bs4 import BeautifulSoup import requests pages = ['https://terminology.collectionstrust.org.uk/British-Museum-objects/Obthesa1.htm'] b = 1 for bp in pages: response = requests.get(bp) html = response.text soup = BeautifulSoup(html, "lxml") for blockquote in soup.find_all('blockquote'): prev_p = blockquote.find_previous('p') prev_text = prev_p.text.strip() if prev_p else "" p_container = blockquote.find('p') if not p_container: continue # 把所有<br>标签替换成换行符 for br in p_container.find_all('br'): br.replace_with('\n') # 提取所有文本,按换行拆分,过滤空行 lines = [line.strip() for line in p_container.get_text().split('\n') if line.strip()] # 输出每一行 for line in lines: print(b, prev_text, line) b += 1
代码说明:
- 先把
<p>里的所有<br>替换成换行符\n,这样原来的分段就变成了文本里的换行分隔。 - 用
get_text()提取<p>的所有文本(自动合并所有子标签的文本),再按换行符拆分,最后过滤掉空行就得到了我们要的每一行。
这两种方法都能得到你想要的结果:
2 ABAYAH RT CLOAK 2 ABAYAH RT COAT 2 ABAYAH BT GARMENT 2 ABAYAH NP ABBA
内容来源于stack exchange
相关产品推荐
相关产品推荐

