BeautifulSoup嵌套类选择器

时间:2017-02-04 08:18:47

标签: 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>

现在我想抓住div类'apple'中的文本,该文章属于'fruits'

这是我到目前为止所尝试的......

for node in soup.find_all("div", class_="apple")

它的回归......

  • 比尔
  • 肖恩

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

  • 约翰
  • 萨姆
  • 贝利
  • 杰克
  • 咸味
  • 水果很好

请注意,我不知道 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)

我不确定如何使用带有BeautifulSoup find_all的嵌套选择器?

非常感谢任何帮助。

谢谢

1 个答案:

答案 0 :(得分:0)

soup.select('.fruits .apple p')

使用CSSselector,表达课程非常容易。

soup.find(class_='fruits').find(class_="apple").find_all('p')

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

编辑:

[s  for div in soup.select('.fruits .apple') for s in div.stripped_strings]

使用strings生成器获取div标记下的所有字符串,stripped_strings将删除结果中的\n

出:

['John', 'Sam', 'Bailey', 'Jack', 'Sour', 'Sweet', 'Salty', 'Fruits are good']

完整代码:

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]