当您想用作 css 选择器时,您应该使用 .select()。在这种情况下,holders = soup.select('div', class_='n0m7sa-0 kkBhMM') 类部分基本上被忽略了......它会找到所有具有任何类的<div>。要指定该特定类,请使用.find_all(),或更改您的.select()
holders = soup.select('div.n0m7sa-0.kkBhMM')
或
holders = soup.find_all('div', class_='n0m7sa-0 kkBhMM')
现在在这两种情况下,它都会返回None 或一个空列表。那是因为该类属性不在源 html 中。该站点是动态的,因此这些类是在初始请求之后生成的。所以要么需要先用Selenium渲染页面,然后拉取html,要么看看有没有api直接获取数据源。
有一个api可以获取数据:
import requests
import pandas as pd
alpha = ['count', 'ratio']
payload = {
'id': '1',
'range': '7d'}
for each in alpha:
url = f'https://api.coinmarketcap.com/data-api/v3/cryptocurrency/detail/holders/{each}'
jsonData = requests.get(url, params=payload).json()['data']['points']
if each == 'count':
count_df = pd.DataFrame.from_dict(jsonData,orient='index')
count_df = count_df.rename(columns={0:'Total Addresses'})
else:
ratio_df = pd.DataFrame.from_dict(jsonData,orient='index')
df = count_df.merge(ratio_df, how='left', left_index=True, right_index=True)
df = df.sort_index()
输出:
print(df.to_string())
Total Addresses topTenHolderRatio topTwentyHolderRatio topFiftyHolderRatio topHundredHolderRatio
2021-11-24T00:00:00Z 39279627 5.25 7.19 10.51 13.26
2021-11-25T00:00:00Z 39255811 5.25 7.19 10.49 13.22
2021-11-26T00:00:00Z 39339840 5.25 7.19 10.51 13.24
2021-11-27T00:00:00Z 39391849 5.23 7.11 10.45 13.18
2021-11-28T00:00:00Z 39505340 5.24 7.11 10.45 13.18
2021-11-29T00:00:00Z 39502099 5.24 7.11 10.43 13.16
2021-11-30T00:00:00Z 39523000 5.24 7.11 10.38 13.12
您的其他选项是数据位于 json 格式的 <script> 标记内。 S0,您也可以通过这种方式从初始请求站点中将其拉出:
from bs4 import BeautifulSoup
import requests
import json
import re
url = 'https://coinmarketcap.com/currencies/bitcoin/holders/'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
jsonStr = str(soup.find('script', {'id':'__NEXT_DATA__'}))
jsonStr = re.search(r"({.*})", jsonStr).groups()[0]
jsonData = json.loads(jsonStr)['props']['initialProps']['pageProps']['info']['holders']
df = pd.DataFrame(jsonData).drop('holderList', axis=1).drop_duplicates()
输出:
print(df.to_string())
holderCount dailyActive topTenHolderRatio topTwentyHolderRatio topFiftyHolderRatio topHundredHolderRatio
0 39523000 963625 5.24 7.11 10.38 13.12
对于 Project Info 中的社会统计,这是在特定的 api 中:
import requests
import pandas as pd
url = 'https://api.coinmarketcap.com/data-api/v3/project-info/detail?slug=bitcoin'
jsonData = requests.get(url).json()
socialStats = jsonData['data']['socialStats']
row = {}
for k, v in socialStats.items():
if type(v) == dict:
row.update(v)
else:
row.update({k:v})
df = pd.DataFrame([row])
输出:
print(df.to_string())
cryptoId commits contributors stars forks watchers lastCommitAt members updatedTime
0 1 31588 836 59687 30692 3881 2021-11-30T00:09:02.000Z 3617460 2021-11-30T16:00:02.365Z