【问题标题】:How to grab first child of its kind如何抓住同类中的第一个孩子
【发布时间】:2020-02-20 06:01:30
【问题描述】:

我正在尝试从两个具有相同名称的节点捕获数据。我正在使用 find 方法,但它总是提取嵌套的值,而不是第一个子节点。我尝试了几种不同的目标方法,但没有任何成功。一如既往地感谢任何帮助。

API Response:


<affiliate_export_response>
  <success>true</success>
  <row_count>1</row_count>
  <affiliates>
      <blacklists>
        <blacklist>
          <advertiser>
            <advertiser_id xmlns="API:id_name_store">2</advertiser_id>
            <advertiser_name xmlns="API:id_name_store">wayne's Ad</advertiser_name>
          </advertiser>
          <affiliate>
            <affiliate_id xmlns="API:id_name_store">3</affiliate_id>
            <affiliate_name xmlns="API:id_name_store">Mark Affiliate</affiliate_name>
          </affiliate>
          <blacklist_reason>
            <blacklist_reason_id xmlns="API:id_name_store">1</blacklist_reason_id>
            <blacklist_reason_name xmlns="API:id_name_store">404</blacklist_reason_name>
          </blacklist_reason>
          <blacklist_type>
            <blacklist_type_id xmlns="API:id_name_store">3</blacklist_type_id>
            <blacklist_type_name xmlns="API:id_name_store">404</blacklist_type_name>
          </blacklist_type>
          <date_created>2018-04-26T00:00:00</date_created>
        </blacklist>
      </blacklists>
      <date_created>2018-01-29T11:40:58.34</date_created>
      <notes />
    </affiliate>
  </affiliates>
</affiliate_export_response>

Code:

import requests
from bs4 import BeautifulSoup

url = 'API URL'
params = {
          'param1':'dfasdf',
          'param2':3
          }
r = requests.get(url, params=params)
soup = BeautifulSoup(r.text, 'lxml')
for affiliate in soup.select('affiliate'):
     date_created = affiliate.find('date_created').string
     print(date_created)

目标是捕获 2018-01-29T11:40:58.34,但我正在捕获黑名单中的嵌套 date_created 节点并获取 2018-04-26T00:00:00。

【问题讨论】:

标签: python python-3.x xml beautifulsoup


【解决方案1】:

在这个使用 bs4 4.7.1+ 的特定示例中,您可以在关联节点的循环中使用 nth-child(even)。

import requests
from bs4 import BeautifulSoup as bs

html = '''
<affiliate_export_response>
    <success>true</success>
    <row_count>1</row_count>
    <affiliates>
        <affiliate>
        <blacklists>
          <blacklist>
            <advertiser>
              <advertiser_id xmlns="API:id_name_store">2</advertiser_id>
              <advertiser_name xmlns="API:id_name_store">wayne's Ad</advertiser_name>
            </advertiser>
            <affiliate>
              <affiliate_id xmlns="API:id_name_store">3</affiliate_id>
              <affiliate_name xmlns="API:id_name_store">Mark Affiliate</affiliate_name>
            </affiliate>
            <blacklist_reason>
              <blacklist_reason_id xmlns="API:id_name_store">1</blacklist_reason_id>
              <blacklist_reason_name xmlns="API:id_name_store">404</blacklist_reason_name>
            </blacklist_reason>
            <blacklist_type>
              <blacklist_type_id xmlns="API:id_name_store">3</blacklist_type_id>
              <blacklist_type_name xmlns="API:id_name_store">404</blacklist_type_name>
            </blacklist_type>
            <date_created>2018-04-26T00:00:00</date_created>
          </blacklist>
        </blacklists>
        <date_created>2018-01-29T11:40:58.34</date_created>
        <notes />
      </affiliate>
    </affiliates>
  </affiliate_export_response>
'''
soup = bs(html, 'lxml')
for item in soup.select('affiliate'):
    date = item.select_one('date_created:nth-child(even)')
    if date is None:
        print('N/A')
    else:
        print(date.text)

【讨论】:

    【解决方案2】:

    首先,您缺少affiliate 的标签开头,这将使您的解析器出错

    <affiliate_export_response>
        <success>true</success>
        <row_count>1</row_count>
        <affiliates>
            <affiliate> ======================= This was missing ================
            <blacklists>
              <blacklist>
                <advertiser>
                  <advertiser_id xmlns="API:id_name_store">2</advertiser_id>
                  <advertiser_name xmlns="API:id_name_store">wayne's Ad</advertiser_name>
                </advertiser>
                <affiliate>
                  <affiliate_id xmlns="API:id_name_store">3</affiliate_id>
                  <affiliate_name xmlns="API:id_name_store">Mark Affiliate</affiliate_name>
                </affiliate>
                <blacklist_reason>
                  <blacklist_reason_id xmlns="API:id_name_store">1</blacklist_reason_id>
                  <blacklist_reason_name xmlns="API:id_name_store">404</blacklist_reason_name>
                </blacklist_reason>
                <blacklist_type>
                  <blacklist_type_id xmlns="API:id_name_store">3</blacklist_type_id>
                  <blacklist_type_name xmlns="API:id_name_store">404</blacklist_type_name>
                </blacklist_type>
                <date_created>2018-04-26T00:00:00</date_created>
              </blacklist>
            </blacklists>
            <date_created>2018-01-29T11:40:58.34</date_created>
            <notes />
          </affiliate>
        </affiliates>
      </affiliate_export_response>
    

    仅使用它来获取附属公司的创建日期

    from bs4 import BeautifulSoup
    soup = BeautifulSoup(text, 'html.parser')
    for affiliate in soup.select('affiliate > date_created'):
         parent = affiliate.parent
         print(affiliate.text)
    

    演示: Here

    【讨论】:

    • 感谢您的详细回复并指出缺少开始标签。在发布前的编辑过程中错过了这个。我有一个后续问题。我已经在查看附属节点中的几个数据点。我需要找到在创建的 for 循环中创建的日期。否则,我只是针对会员> date_created。关于如何在我的 for 循环中找到这个值的任何建议,在 soup.select('affiliate'):
    猜你喜欢
    • 2022-10-19
    • 2017-03-11
    • 2022-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    相关资源
    最近更新 更多