我正在从包含很多div标签的html文件中提取文本。但是,在某些地方,有4个嵌套的div标签,当我打印文本时,它会打印4次。
<div>
<div id="PGBRK" style="TEXT-INDENT: 0pt; WIDTH: 100%; MARGIN-LEFT: 0pt; MARGIN-RIGHT: 0pt">
<div id="PN" style="PAGE-BREAK-AFTER: always; WIDTH: 100%">
<div style="TEXT-ALIGN: center; WIDTH: 100%"><font style="DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 10pt">27</font></div>
</div>
</div>
</div>
例如,在这里,如果我这样做:
for item in page_soup.find_all('div'):
if "27" in item.text:
print(item)
它将数字27打印四次,因此弄乱了整个文本。 如何获得我的代码仅打印嵌套文本一次?
编辑1: 这对于代码的这一部分效果很好。但是就像我说的那样,这仅在某些地方是正确的。例如,当我这样做时:
for item in page_soup.find_all('div', recursive = False):
print(item)
它不打印任何内容。作为参考,this是我要抓取的文档。
编辑2: 我正在从给定的html中提取“ ITEM 1A。风险因素”部分。
should_print = False
for item in page_soup.find_all('div'):
if "ITEM 1A." in item.text:
should_print = True
elif "ITEM 1B." in item.text:
break
if should_print:
print(item)
因此,我正在打印从ITEM 1A开始的所有内容。直到找到ITEM 1B。 在某些地方,有嵌套的div标签,此代码多次将其打印出来。
如果我这样做,则递归= False,它不会打印任何内容。
答案 0 :(得分:0)
您可以提供选项text = "27"
来按文本搜索div并仅标识该确切的div。下面的代码应该可以正常工作。如果要获取所有div,则只需删除text = "27"
或将其替换为要查找的文本。您也可以使用recursive = False
仅获取顶级div。
from bs4 import BeautifulSoup
t = '''
<div>
27
</div>
<div>
<div id="PGBRK" style="TEXT-INDENT: 0pt; WIDTH: 100%; MARGIN-LEFT: 0pt; MARGIN-RIGHT: 0pt">
<div id="PN" style="PAGE-BREAK-AFTER: always; WIDTH: 100%">
<div style="TEXT-ALIGN: center; WIDTH: 100%"><font style="DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 10pt">27</font></div>
</div>
</div>
</div>
</div>
'''
page_soup = BeautifulSoup(t, 'html.parser')
for item in page_soup.find_all('div', text="27"):
print(item.text)
我添加了一个特定代码,专门用于解决您的问题。试试下面的代码。您期望的div范围是从567 - 715
中删除的页码。
import requests
from bs4 import BeautifulSoup
resp = requests.get(
r'https://www.sec.gov/Archives/edgar/data/4904/000000490412000013/ye11aep10k.htm')
t = resp.text
page_soup = BeautifulSoup(t, 'html.parser')
s = 'body > div:not(#PGBRK)'
for i in page_soup.select(s)[567:715]:
print(i.get_text(strip=True))
答案 1 :(得分:0)
这是一个选择
import bs4, re
html = '''<div>
<div id="PGBRK" style="TEXT-INDENT: 0pt; WIDTH: 100%; MARGIN-LEFT: 0pt; MARGIN-RIGHT: 0pt">
<div id="PN" style="PAGE-BREAK-AFTER: always; WIDTH: 100%">
<div style="TEXT-ALIGN: center; WIDTH: 100%"><font style="DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 10pt">27</font></div>
</div>
</div>
</div>
</div>'''
soup = bs4.BeautifulSoup(html,'html.parser')
elements = soup.find_all(text=re.compile('27'))
print(elements)
输出
[u'27']
答案 2 :(得分:0)
打印从
ITEM 1A
开始的所有内容。直到找到ITEM 1B
低谷.string
属性(https://www.crummy.com/software/BeautifulSoup/bs4/doc/#string)
import requests
from bs4 import BeautifulSoup
url = 'https://www.sec.gov/Archives/edgar/data/4904/000000490412000013/ye11aep10k.htm'
html_doc = requests.get(url).content
page_soup = BeautifulSoup(html_doc, 'html.parser')
do_print = False
for el in page_soup.find_all('div'):
if el.string:
if "ITEM 1A" in el.string:
do_print = True
elif "ITEM 1B" in el.string:
break
if do_print:
print(el)
输出(我将显示不带中间部分的代表性开始和结束块,以进行简短的转储):
<div align="justify" style="TEXT-INDENT: 0pt; DISPLAY: block; MARGIN-LEFT: 0pt; MARGIN-RIGHT: 0pt"><font style="DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 12pt; FONT-WEIGHT: bold"><font style="DISPLAY: inline; TEXT-DECORATION: underline">ITEM 1A. RISK FACTORS</font></font></div>
<div style="TEXT-INDENT: 0pt; DISPLAY: block"><br/>
</div>
<div align="justify" style="TEXT-INDENT: 0pt; DISPLAY: block; MARGIN-LEFT: 0pt; MARGIN-RIGHT: 0pt"><font style="DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 12pt; FONT-WEIGHT: bold">GENERAL RISKS OF OUR REGULATED OPERATIONS</font></div>
<div style="TEXT-INDENT: 0pt; DISPLAY: block">
<div align="justify" style="TEXT-INDENT: 0pt; DISPLAY: block; MARGIN-LEFT: 0pt; MARGIN-RIGHT: 0pt"><font style="FONT-STYLE: italic; DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 12pt; FONT-WEIGHT: bold"> </font></div>
<div align="justify" style="TEXT-INDENT: 0pt; DISPLAY: block; MARGIN-LEFT: 0pt; MARGIN-RIGHT: 0pt"><font style="FONT-STYLE: italic; DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 12pt; FONT-WEIGHT: bold">The regulatory environment in Ohio has recently become unpredictable and increasingly uncertain. – Affecting AEP and OPCo</font></div>
<div style="TEXT-INDENT: 0pt; DISPLAY: block"><br/>
.....
<div style="TEXT-ALIGN: center; WIDTH: 100%"><font style="DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 10pt">37</font></div>
<div style="TEXT-ALIGN: center; WIDTH: 100%">
<hr noshade="" size="2" style="COLOR: black"/>
</div>
<div id="HDR">
<div align="right" id="GLHDR" style="WIDTH: 100%"><font style="DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 8pt"> </font></div>
</div>
<div align="right" id="GLHDR" style="WIDTH: 100%"><font style="DISPLAY: inline; FONT-FAMILY: Times New Roman; FONT-SIZE: 8pt"> </font></div>
<div style="TEXT-INDENT: 0pt; DISPLAY: block"> </div>
答案 3 :(得分:0)
好吧,我认为这是一个很酷的问题,如果您想对它进行概括以找出每个级别上存在哪些文本,而又不求助于像27这样的特定数字,那么我看不到一个简单的答案。Beautiful Soup似乎没有只在顶部显示文本的功能,而recursive = False只是阻止搜索深入到第一级以下,但仍将第一级以下的所有内容都包括在内,因此,如果在顶级标签,它将捕获它及其下面的所有内容
因此,我认为您实际上必须递归divs树并在每个级别上比较文本。我明白了。在递归中冒泡时,它以相反的顺序打印,但可以存储在列表中并以向前的顺序输出。
from bs4 import BeautifulSoup
soup = BeautifulSoup('<div>1A<div>2A</div>1B<div>2B<div>3A</div><div>3A</div>2C</div>1C</div>', 'html.parser')
def mangle(node):
divs = node.find_all('div')
if len(divs):
result = [divs[0]] + [n for n in divs[0].next_siblings if n.__class__.__name__ == 'Tag']
txt = []
for r in result:
txt.append(r.__repr__())
for c in mangle(r):
txt[-1] = txt[-1].replace(c.__repr__(), '')
print(''.join(BeautifulSoup(t, 'html.parser').text for t in txt))
return result
else:
return []
if __name__ == '__main__':
mangle(soup)
基本上,它沿着div的分支移动,并在树的每个分支上建立列表,包括标签,然后调用者删除其下找到的所有内容,仅保留在该级别定义的文本。我将标签保留在适当的位置,以便不会误删除出现在多个级别的文本模式。
html 1A2A1B2B3A3A2C1C的输出为
3A3A
2A2B2C
1A1B1C
分别是第三,第二和第一嵌套级别。希望这会有所帮助。
答案 4 :(得分:0)
自从我终于开始工作以来,我将回答我自己的问题。
解决方案很简单,我只是觉得太难了。 我只是添加了条件,即该项目的父项不应该是“ div”。现在,该程序不会多次打印文本。
should_print = False
for item in page_soup.find_all('div'):
if item.name == "div" and item.parent.name != "div"
if "ITEM 1A." in item.text:
should_print = True
elif "ITEM 1B." in item.text:
break
if should_print:
print(item)
感谢大家的贡献。感激...