BeautifulSoup 嵌套类选择器

Sly*_*per 5 beautifulsoup

我正在为一个项目使用 BeautifulSoup。这是我的 HTML 结构

<div class="container">
<div class="fruits">
    <div class="apple">
        <p>John</p>
        <p>Sam</p>
        <p>Bailey</p>
        <p>Jack</p>
        <ul>
            <li>Sour</li>
            <li>Sweet</li>
            <li>Salty</li>
        </ul>
        <span>Fruits are good</span>
    </div>
    <div class="mango">
        <p>Randy</p>
        <p>James</p>
    </div>
</div>
<div class="apple">
    <p>Bill</p>
    <p>Sean</p>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)

现在我想在属于“水果”div 类“apple”中获取文本

这是我迄今为止尝试过的......

for node in soup.find_all("div", class_="apple")
Run Code Online (Sandbox Code Playgroud)

它的回归...

  • 账单
  • 肖恩

但我希望它只返回......

  • 约翰
  • 山姆
  • 贝利
  • 杰克
  • 酸的
  • 甜的
  • 水果不错

请注意,我不知道div class="apple"中元素的确切结构。该类中可以有任何类型的不同 HTML 元素。所以选择器必须足够灵活。

这是完整的代码,我需要在其中添加此 BeautifulSoup 代码...

class MySpider(CrawlSpider):
name = 'dknnews'
start_urls = ['http://www.example.com/uat-area/scrapy/all-news-listing/_recache']
allowed_domains = ['example.com']
def parse(self, response):
        hxs = Selector(response)
        soup = BeautifulSoup(response.body, 'lxml')
        #soup = BeautifulSoup(content.decode('utf-8','ignore'))
        nf = NewsFields()
        ptype = soup.find_all(attrs={"name":"dknpagetype"})
        ptitle = soup.find_all(attrs={"name":"dknpagetitle"})
        pturl = soup.find_all(attrs={"name":"dknpageurl"})
        ptdate = soup.find_all(attrs={"name":"dknpagedate"})
        ptdesc = soup.find_all(attrs={"name":"dknpagedescription"})
        for node in soup.find_all("div", class_="apple"): <!-- THIS IS WHERE I NEED TO ADD THE BS CODE -->
         ptbody = ''.join(node.find_all(text=True))
         ptbody = ' '.join(ptbody.split())
         nf['pagetype'] = ptype[0]['content'].encode('ascii', 'ignore')
         nf['pagetitle'] = ptitle[0]['content'].encode('ascii', 'ignore')
         nf['pageurl'] = pturl[0]['content'].encode('ascii', 'ignore')
         nf['pagedate'] = ptdate[0]['content'].encode('ascii', 'ignore')
         nf['pagedescription'] = ptdesc[0]['content'].encode('ascii', 'ignore')
         nf['bodytext'] = ptbody.encode('ascii', 'ignore')
         yield nf
        for url in hxs.xpath('//ul[@class="scrapy"]/li/a/@href').extract():
         yield Request(url, callback=self.parse)
Run Code Online (Sandbox Code Playgroud)

我不确定如何在 BeautifulSoup find_all 中使用嵌套选择器?

非常感谢任何帮助。

谢谢

宏杰李*_*宏杰李 5

soup.select('.fruits .apple p')
Run Code Online (Sandbox Code Playgroud)

使用CSSselector,很容易表达类。

soup.find(class_='fruits').find(class_="apple").find_all('p')
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用find()逐步获取p标签

编辑:

[s  for div in soup.select('.fruits .apple') for s in div.stripped_strings]
Run Code Online (Sandbox Code Playgroud)

使用strings生成器获取div标签下的所有字符串,stripped_strings\n在结果中去掉。

出去:

['John', 'Sam', 'Bailey', 'Jack', 'Sour', 'Sweet', 'Salty', 'Fruits are good']
Run Code Online (Sandbox Code Playgroud)

完整代码:

from bs4 import BeautifulSoup
source_code = """<div class="container">
<div class="fruits">
    <div class="apple">
        <p>John</p>
        <p>Sam</p>
        <p>Bailey</p>
        <p>Jack</p>
        <ul>
            <li>Sour</li>
            <li>Sweet</li>
            <li>Salty</li>
        </ul>
        <span>Fruits are good</span>
    </div>
    <div class="mango">
        <p>Randy</p>
        <p>James</p>
    </div>
</div>
<div class="apple">
    <p>Bill</p>
    <p>Sean</p>
</div>
</div>
"""
soup = BeautifulSoup(source_code, 'lxml')
[s  for div in soup.select('.fruits .apple') for s in div.stripped_strings]
Run Code Online (Sandbox Code Playgroud)