【问题标题】:How can I pull specific nested elements with the same tag in Beautiful Soup?如何在 Beautiful Soup 中提取具有相同标签的特定嵌套元素?
【发布时间】:2019-08-14 12:41:49
【问题描述】:

我对 Python 很陌生,所以我仍在尝试找出 Beautiful Soup。我正在尝试抓取一个网站并提取五个紧跟我在代码中找到的标签的元素。

我尝试了 next.element,它只提取我在 soup.find 中使用的标签的文本,我尝试了 next.sibling,它返回为空白。

页面上有许多“first”和“last”类,所以我必须指定我想要的文本行。这是我要抓取的内容:

 <li>
        <ul>
            <li class="first">Maintenance</li>
                        <li>$number1</li>
                        <li>$number2</li>
                        <li>$number3</li>
                        <li>$number4</li>
                        <li>$number5</li>
                    <li class="last">$linetotal</li>
        </ul>
    </li>

这是我正在尝试的:

for x,y in zip(make, model):
    url = ('https://URL with variables goes here')
    headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'}
    search = requests.get(url, headers = headers)
    html = search.text
    soup = BeautifulSoup(html, 'lxml')
    search_results = soup.find('li', class_ = 'first', text = re.compile('Maintenance'))
    try:
        d = search_results.next_element
        print(d)
    except:
        print('pass')  

最终目标是将 number1:number5 的数组附加到一个列表中,但使用上面的代码,输出只是“维护”。我哪里错了?另外,由于我是新人,如果您也能提供上下文,我将非常感激。

【问题讨论】:

  • 您是否希望每次出现类都先进行文本维护,然后是 li 孩子?还是只有第一次出现?可以分享一下网址吗?维护是否只发生一次且位置固定?

标签: python web-scraping beautifulsoup


【解决方案1】:

类似于 QHarr 的回答,但有些不同:

 h = '''
   <li>
     <ul>
       <li class="first">Maintenance</li>
       <li>$number1</li>
       <li>$number2</li>
       <li>$number3</li>
       <li>$number4</li>
       <li>$number5</li>
       <li class="last">$linetotal</li>
   </ul>
</li>

  '''
from lxml import etree
doc = etree.fromstring(h)
for cost in doc.xpath('//li'): 
   if not 'class' in cost.attrib:
      print(cost.text)

输出:

$number1
$number2
$number3
$number4
$number5

【讨论】:

    【解决方案2】:

    您可以将 xpath 表达式与 tree.xpath 之类的东西一起使用

    //li[@class='first' and text()='Maintenance']/following-sibling::li[not(@class)]
    

    例如

    from lxml.html import fromstring
    # url = ''
    # tree = html.fromstring( requests.get(url).content)
    h = '''
     <li>
        <ul>
            <li class="first">Maintenance</li>
            <li>$number1</li>
            <li>$number2</li>
            <li>$number3</li>
            <li>$number4</li>
            <li>$number5</li>
            <li class="last">$linetotal</li>
        </ul>
    </li>
    '''
    tree = fromstring(h)
    items = [item.text for item in tree.xpath("//li[@class='first' and text()='Maintenance']/following-sibling::li[not(@class)]")]
    print(items)
    

    【讨论】:

    • 你试过了吗?您的问题指定了您想在维护后找到。这个解决方案就是这样做的
    【解决方案3】:

    根据您的示例,最简单的方法是将所有未定义类的 li 元素附加到结果列表中。

    from bs4 import BeautifulSoup
    
    html = """ <li>
            <ul>
                <li class="first">Maintenance</li>
                            <li>$number1</li>
                            <li>$number2</li>
                            <li>$number3</li>
                            <li>$number4</li>
                            <li>$number5</li>
                        <li class="last">$linetotal</li>
            </ul>
        </li>"""
    
    soup = BeautifulSoup(html, 'lxml')
    start = soup.find('li', class_ = 'first').parent
    result = []
    
    for ele in start.find_all('li'):
    
        if not ele.get('class'):
            result.append(ele.text)
    
    print(result)
    

    输出:

    ['$number1', '$number2', '$number3', '$number4', '$number5']
    

    【讨论】:

      猜你喜欢
      • 2020-07-04
      • 2019-11-06
      • 1970-01-01
      • 2020-08-24
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多