抓取动态网页的数据使用scrapy
crawl dynamic webpage for data using scrapy
我试图从NBA的官方统计数据中获得一些数据,用于一些数据分析。我使用scrapy作为刮痧的主要工具。然而,在检查网页元素后,我发现它是使用javascript动态生成的。我对javascript完全陌生,无法弄清楚它实际上是如何工作的。(哪个js文件被调用,它是如何加载到其中包含数据表以及是否有更容易访问的方式来获取数据)我也在网络中找到了一些json文件,我不知道如何使用。
http://stats.nba.com/teamLineups.html?TeamID=1610612739& pageNo = 1, rowsPerPage = 100,赛季= 2008 - 09 -,sortField = MIN&排序方式= DES& PerMode = Per48
任何人谁可以指导我使用上面的url,并告诉我如何网站的实际功能,以加载数据,以及他们如何处理数据,使其以这种方式显示?
关键的部分仍然是如何获取数据。我已经看到了使用POST方法来获取数据的答案(对不起,我甚至不熟悉get/POST),但我仍然无法弄清楚这如何适用于此上下文中。
感谢您的慷慨指导!
在这个例子中,Javascript只允许在网页上发送、接收和显示内容,而不需要为每个请求重新加载网页。因此,您不需要解析javascript,只需找到请求的信息,然后模仿该请求,并解析响应。为此,您可以使用Firefox中的Firebug,或者Chrome中的开发人员工具(windows中的ctrl+shift+J, Mac中的cmd+opt+J)。在Chrome浏览器中,只需单击"网络"选项卡,当您单击网站时,您将看到请求和响应。
在这个特殊的例子中,当你想获得克利夫兰队2008-09赛季的统计数据时,javascript会发送多个请求。对阵容的要求,你可能会感兴趣,是这样的:http://stats.nba.com/stats/teamdashlineups?PlusMinus=N&pageNo=1&GroupQuantity=5&TeamID=1610612739&GameID=&Location=&SeasonType=Regular+Season&Season=2008-09&PaceAdjust=N&DateFrom=&sortOrder=DES&VsConference=&OpponentTeamID=0&DateTo=&GameSegment=&LastNGames=0&VsDivision=&LeagueID=00&Outcome=&GameScope=&MeasureType=Base&PerMode=Per48&sortField=MIN&SeasonSegment=&Period=0&Rank=N&Month=0&rowsPerPage = 100
这是一个scrapy base spider的例子。您只需要定义LineupItem,然后您可以使用scrapy crawl stats -o output.json
执行它。
import json
from scrapy.spider import Spider
from scrapy.http import Request
from nba.items import LineupItem
from urllib import urlencode
class StatsSpider(Spider):
name = "stats"
allowed_domains = ["stats.nba.com"]
start_urls = (
'http://stats.nba.com/',
)
def parse(self, response):
return self.get_lineup('1610612739','2008-09')
def get_lineup(self, team_id, season):
params = {
'Season': season,
'SeasonType': 'Regular Season',
'LeagueID': '00',
'TeamID': team_id,
'MeasureType': 'Base',
'PerMode': 'Per48',
'PlusMinus': 'N',
'PaceAdjust': 'N',
'Rank': 'N',
'Outcome': '',
'Location': '',
'Month': '0',
'SeasonSegment': '',
'DateFrom': '',
'DateTo': '',
'OpponentTeamID': '0',
'VsConference': '',
'VsDivision': '',
'GameSegment': '',
'Period': '0',
'LastNGames': '0',
'GroupQuantity': '5',
'GameScope': '',
'GameID': '',
'pageNo': '1',
'rowsPerPage': '100',
'sortField': 'MIN',
'sortOrder': 'DES'
}
return Request(
url="http://stats.nba.com/stats/teamdashlineups?" + urlencode(params),
dont_filter=True,
callback=self.parse_lineup
)
def parse_lineup(self,response):
data = json.loads(response.body)
for lineup in data['resultSets'][1]['rowSet']:
item = LineupItem()
item['group_set'] = lineup[0]
item['group_id'] = lineup[1]
item['group_name'] = lineup[2]
item['gp'] = lineup[3]
item['w'] = lineup[4]
item['l'] = lineup[5]
item['w_pct'] = lineup[6]
item['min'] = lineup[7]
item['fgm'] = lineup[8]
item['fga'] = lineup[9]
item['fg_pct'] = lineup[10]
item['fg3m'] = lineup[11]
item['fg3a'] = lineup[12]
item['fg3_pct'] = lineup[13]
item['ftm'] = lineup[14]
item['fta'] = lineup[15]
item['ft_pct'] = lineup[16]
item['oreb'] = lineup[17]
item['dreb'] = lineup[18]
item['reb'] = lineup[19]
item['ast'] = lineup[20]
item['tov'] = lineup[21]
item['stl'] = lineup[22]
item['blk'] = lineup[23]
item['blka'] = lineup[24]
item['pf'] = lineup[25]
item['pfd'] = lineup[26]
item['pts'] = lineup[27]
item['plus_minus'] = lineup[28]
yield item
将生成如下json记录:
{"gp": 30, "fg_pct": 0.491, "group_name": "Ilgauskas,Zydrunas - James,LeBron - Wallace,Ben - West,Delonte - Williams,Mo", "group_set": "Lineups", "w_pct": 0.833, "pts": 103.0, "min": 484.9866666666667, "tov": 13.3, "fta": 21.6, "pf": 16.0, "blk": 7.7, "reb": 44.2, "blka": 3.0, "ftm": 16.6, "ft_pct": 0.771, "fg3a": 18.7, "pfd": 17.2, "ast": 23.3, "fg3m": 7.4, "fgm": 39.5, "fg3_pct": 0.397, "dreb": 32.0, "fga": 80.4, "plus_minus": 18.4, "stl": 8.3, "l": 5, "oreb": 12.3, "w": 25, "group_id": "980 - 2544 - 1112 - 2753 - 2590"}
Scrapy不能运行javascript,所以你必须分析javascript代码并在Python和Scrapy中做类似的事情,或者识别javascript如何从服务器获取数据(它使用的url和参数)并使用它的脚本。这可能会有很多工作——首先是Firefox中的Firebug,然后是Python和Scrapy。
如果你不知道如何做到这一点,最好使用Selenium
(或类似的东西),模拟真实的浏览器,可以运行javascript。你只需要告诉Selenium
哪个按钮按在页面上,什么文本放在表格中,等等。
import requests
import json
# set request as GET
response = requests.get('http://stats.nba.com/stats/teamdashlineups?Season=2008-09&SeasonType=Regular+Season&LeagueID=00&TeamID=1610612739&MeasureType=Base&PerMode=Per48&PlusMinus=N&PaceAdjust=N&Rank=N&Outcome=&Location=&Month=0&SeasonSegment=&DateFrom=&DateTo=&OpponentTeamID=0&VsConference=&VsDivision=&GameSegment=&Period=0&LastNGames=0&GroupQuantity=5&GameScope=&GameID=&pageNo=1&rowsPerPage=100&sortField=MIN&sortOrder=DES')
# change json into dictionary
data = json.loads(response.text)
#print data
import pprint
pprint.pprint(data)
for x in data['resultSets']:
print x['rowSet']
我可能无法详细回答你的问题,但这是我的理解。
当你去一个页面的浏览器GET
的源代码的页面,相同的源代码,你看到当你点击"查看页面源代码"在chrome。浏览器解释代码,当它发现指向外部文件的"src"属性时,它将该文件导入源文件,同样使用GET
请求。
<script src="/js/libs/modernizr.custom.16166.js"></script>
一旦JavaScript文件被导入,他们就可以运行它们了
jsfile.js:
function myFunction() {
//
//do stuff
//
}
myFunction();
在您的nba站点中,导入的文件创建表并使用ajax GET
请求填充它。
你的nba网站似乎从这个链接使用ajax GET
请求从"jquery.statrequest.js"answers"team-lineup .js"得到表信息,这是一个烂摊子,所以你可能仍然要正常刮页。
如果你决定抓取页面,你将无法使用urllib,因为它只获取页面源代码,它不导入任何外部.js脚本,也不运行JavaScript代码,在这种情况下,页面上的表不会被创建和填充nba统计数据。
您将需要使用类似Mechanize的东西,它模拟浏览器并导入和运行JavaScript。
我希望这能给你一些你想知道的想法,我不是很熟悉浏览器的内部工作原理。你可能想找一个网站,有免费的API的nda游戏统计。
这是另一个来自nba网站的链接,可能与你有关。
- 用程序搜索JQuery数据表中的文本
- 要求输入在数据列表中
- 正在将数据主题添加到所有项目
- 函数参数中的数据与指定变量之间的任何性能差异
- 在VanillaJS中模拟模型双向数据绑定
- CSS-如何定位内容数据标题
- 使用电话间隙在Android应用程序中显示SQL Lite的数据
- 无法在数据endVal中设置值=“”;{{ucount}}”;使用Angular JS的CountUp
- 序列化数据属性中对象的最可靠方法
- 如何将JSON数据导入我的ejs模板
- 不显示带有本地json文件数据的谷歌地图脚本
- 如何将json数据显示为html
- Scrapy和Xpath从javascript代码中提取数据
- 使用回发数据抓取页面 javascript Python Scrapy
- Scrapy:POST 请求返回 JSON 响应(200 OK),但数据不完整
- 抓取动态网页的数据使用scrapy
- 使用SCRAPY和PYTHON从Javascript中抓取数据
- 如何使用javascript更改后的Scrapy获得抓取数据?
- Scrapy:从javascript生成的表单中抓取数据
- 如何在scrapy中解析JSON数据