【问题标题】:Scraping from specific div without attribute where tags can have the same name从没有属性的特定 div 中抓取标签可以具有相同的名称
【发布时间】:2019-08-25 10:38:15
【问题描述】:

我正试图从 wowhead 上刮一张桌子。问题是跨度类对于 2 种不同类型的数据是相同的(Sell for: 和 Buy for:)。

跨度所在的分区没有类,只有我在括号中写的刺。

我试过了

import requests
from bs4 import BeautifulSoup
import urllib.request
import re
import lxml
session = requests.session()
url1 = 'https://classicdb.ch/?item=4291'
response = session.get(url1)
soup = BeautifulSoup(response.text, 'lxml')

x=(soup.find('table', attrs={'class': "infobox"}))
y=x.find('td')
y=y.find('ul')

sell_silver = soup.select_one('div:contains("Sells for:") .moneysilver').text
buy_silver = y.select_one('div:contains("Buy for:") .moneysilver').text
print(sell_silver)
print(buy_silver)

但我只得到第一个跨度。

我拿到表格后的相关HTML是这样的

<div>
	Buy for:
	<span class="moneysilver">5</span>
</div>
</li>
<li>
<div>
	Sells for:
	<span class="moneysilver">1</span> <span class="moneycopper">25</span>
</div>

....

最终结果应该允许我将数据排序为

Buy_silver=5

Sell_silver=1

编辑以澄清问题并大声喊叫@QHarr

【问题讨论】:

    标签: html python-3.x web-scraping beautifulsoup


    【解决方案1】:

    BS4 4.7.1+ 你可以使用:contains 来定位Buy forSells for

    import requests
    from bs4 import BeautifulSoup as bs
    
    r = requests.get('https://classicdb.ch/?item=4291')
    soup = bs(r.content, 'lxml')
    buy_silver, sell_silver = soup.select_one('li:contains("Buy for") .moneysilver').text , soup.select_one('li:contains("Sells for") .moneysilver').text
    

    【讨论】:

    • 嘿,我似乎很接近你的建议。当我复制您的答案时,我得到相同的结果,但是如果我将其应用于我的代码,则买卖都变为 5。完整的代码如下所示,没有导入库 session = requests.session() url1 = 'classicdb.ch/?item=4291' 响应= session.get(url1) 汤 = BeautifulSoup(response.text, 'lxml') x=(soup.find('table', attrs={'class': "infobox"})) y=x.find(' td') y=y.find('ul') sell_silver = y.select_one('div:contains("售价:") .moneysilver') buy_silver = y.select_one('div:contains("买价:" ) .moneysilver')
    • 是代码还是html?我应用了一些更改以使 html 完整。有网址可以用吗?
    • 是的,classicdb.ch/?item=4291
    • 太棒了,谢谢!我不能投票,否则我会。为什么查找 li 标签而不是 div 会有什么不同?
    • 如果您使用 div,它会选择一个父 div,该 div 实际上包含包含卖出和买入的 div。使用 li 将您带到添加子类一次仅基于 :contains 的级别返回 1
    【解决方案2】:

    假设买入和卖出报价的顺序和距离始终相同,您可以尝试使用这个:

    metal = """
    <li>
    <div>
        Buyfor:
        <span class="moneysilver">5</span>
    </div>
    </li>
    <li>
    <div>
        Sells for:
        <span class="moneysilver">1</span> <span class="moneycopper">25</span>
    </div>
    </li>
    """
    
    from bs4 import BeautifulSoup as bs
    soup = bs(metal, 'lxml')
    silver=soup.find_all('div')
    
    print("buy silver =",silver[0].find("span", class_="moneysilver").text)
    print("sell silver =",silver[1].find("span", class_="moneysilver").text)
    

    输出:

    买白银 = 5

    卖白银 = 1

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-14
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 2013-05-11
      • 1970-01-01
      • 2021-07-10
      • 1970-01-01
      相关资源
      最近更新 更多