美丽的汤没有获得NBA.com数据

时间:2015-01-22 05:39:10

标签: python web-scraping beautifulsoup

我想从此网页上的表中提取数据:http://stats.nba.com/league/team/#!/advanced/。不幸的是,下面的代码没有给我任何东西,因为汤(见下文)不包含“td”,即使在检查网页时有很多“td”。

另一方面,为网站“http://espn.go.com/nba/statistics/team/_/stat/offense-per-game”运行相同的代码确实给了我想要的东西。

为什么代码适用于一个站点而不适用于另一个站点,是否有什么可以从第一个站点获取我想要的数据?


import requests
from bs4 import BeautifulSoup
url="http://stats.nba.com/league/team/#!/advanced/"
r=requests.get(url)
soupNBAadv=BeautifulSoup(r.content)

tds=soupNBAadv.find_all("td")
for i in tds:
    print i.text

2 个答案:

答案 0 :(得分:3)

你根本不需要BeautifulSoup。您在浏览器中看到的表是在额外获取请求的帮助下形成的,该端点返回JSON响应,模拟它:

import requests

url = "http://stats.nba.com/league/team/#!/advanced/"
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36'}

with requests.Session() as session:
    session.headers = headers
    session.get(url, headers=headers)

    params = {
        'DateFrom': '',
        'DateTo': '',
        'GameScope': '',
        'GameSegment': '',
        'LastNGames': '0',
        'LeagueID': '00',
        'Location': '',
        'MeasureType': 'Advanced',
        'Month': '0',
        'OpponentTeamID': '0',
        'Outcome': '',
        'PaceAdjust': 'N',
        'PerMode': 'Totals',
        'Period': '0',
        'PlayerExperience': '',
        'PlayerPosition': '',
        'PlusMinus': 'N',
        'Rank': 'N',
        'Season': '2014-15',
        'SeasonSegment': '',
        'SeasonType': 'Regular Season',
        'StarterBench': '',
        'VsConference': '',
        'VsDivision': ''
    }

    response = session.get('http://stats.nba.com/stats/leaguedashteamstats', params=params)
    results = response.json()
    headers = results['resultSets'][0]['headers']
    rows = results['resultSets'][0]['rowSet']
    for row in rows:
        print(dict(zip(headers, row)))

打印:

{u'MIN': 2074.0, u'TEAM_ID': 1610612737, u'TEAM_NAME': u'Atlanta Hawks', u'AST_PCT': 0.687, u'CFPARAMS': u'Atlanta Hawks', u'EFG_PCT': 0.531, u'DEF_RATING': 99.4, u'NET_RATING': 7.5, u'PIE': 0.556, u'AST_TO': 1.81, u'TS_PCT': 0.57, u'GP': 43, u'L': 8, u'OREB_PCT': 0.21, u'REB_PCT': 0.488, u'W': 35, u'W_PCT': 0.814, u'DREB_PCT': 0.743, u'CFID': 10, u'PACE': 96.17, u'TM_TOV_PCT': 0.149, u'AST_RATIO': 19.9, u'OFF_RATING': 106.9}
{u'MIN': 1897.0, u'TEAM_ID': 1610612738, u'TEAM_NAME': u'Boston Celtics', u'AST_PCT': 0.635, u'CFPARAMS': u'Boston Celtics', u'EFG_PCT': 0.494, u'DEF_RATING': 104.0, u'NET_RATING': -2.7, u'PIE': 0.489, u'AST_TO': 1.73, u'TS_PCT': 0.527, u'GP': 39, u'L': 26, u'OREB_PCT': 0.245, u'REB_PCT': 0.496, u'W': 13, u'W_PCT': 0.333, u'DREB_PCT': 0.747, u'CFID': 10, u'PACE': 99.12, u'TM_TOV_PCT': 0.145, u'AST_RATIO': 18.5, u'OFF_RATING': 101.3}
...

Selenium - 基于解决方案:

from pprint import pprint
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


driver = webdriver.Firefox()
driver.get('http://stats.nba.com/league/team/#!/advanced/')
wait = WebDriverWait(driver, 5)

# wait for the table to load
table = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'table-responsive')))

stats = []
headers = [th.text for th in table.find_elements_by_tag_name('th')]
for tr in table.find_elements_by_xpath('//tr[@data-ng-repeat]'):
    cells = [td.text for td in tr.find_elements_by_tag_name('td')]

    stats.append(dict(zip(headers, cells)))

pprint(stats)

driver.quit()

打印:

[{u'AST Ratio': u'19.8',
  u'AST%': u'68.1',
  u'AST/TO': u'1.84',
  u'DREB%': u'74.3',
  u'DefRtg': u'100.2',
  u'GP': u'51',
  u'MIN': u'2458',
  u'NetRtg': u'7.4',
  u'OREB%': u'21.0',
  u'OffRtg': u'107.7',
  u'PACE': u'96.12',
  u'PIE': u'55.3',
  u'REB%': u'48.8',
  u'TO Ratio': u'14.6',
  u'TS%': u'57.2',
  u'Team': u'Atlanta Hawks',
  u'eFG%': u'53.4'},
  ...
 {u'AST Ratio': u'18.6',
  u'AST%': u'62.8',
  u'AST/TO': u'1.65',
  u'DREB%': u'77.8',
  u'DefRtg': u'100.2',
  u'GP': u'52',
  u'MIN': u'2526',
  u'NetRtg': u'3.5',
  u'OREB%': u'24.9',
  u'OffRtg': u'103.7',
  u'PACE': u'95.75',
  u'PIE': u'53.4',
  u'REB%': u'51.8',
  u'TO Ratio': u'15.4',
  u'TS%': u'54.4',
  u'Team': u'Washington Wizards',
  u'eFG%': u'50.9'}]

答案 1 :(得分:1)

使用requests.get()无法从第一个网址获取数据的原因是,使用ajax调用从服务器获取数据。并且ajax调用url是http://stats.nba.com/stats/leaguedashteamstats。你必须传递一些参数。

进行requests.get()通话时,您只会获得浏览器页面来源中显示的数据。在浏览器中按ctrl+u查看页面源,您可以看到源中没有数据。

在Chrome浏览器中使用开发人员工具,并在Network标签中查看该页面的请求。在Firefox中,您可以使用firebug并在Net标签中查看。

如果是第二个网址,则会在页面源中填充数据(查看要检查的页面源)。因此,您可以通过在特定网址中发出获取请求来获取它。

alecxe的回答演示了如何从第一个网址获取数据。