数据通常有两种呈现模式:服务器端呈现(rendered server-side),客户端呈现(rendered client-side)。如今日益流行的AngularJS等框架导致了前者向后者的转变。利用Python进行网页爬虫,需要厘清两种呈现模式,并且巧妙地寻找潜藏的API。本篇文章与上一篇的运动轨迹呈现有关联,旨在说明实现运动数据分析的基础步骤——数据收集。
Server-side vs Client-side
设想现有一个体育数据库,可以在其顶层建设一个网络应用。如果采用诸如Django等server-side框架建构APP(典型代表:Basketball Reference),那么每当一个用户访问一次网页,就会出现如下流程(这个流程用算法示意图呈现会有更好效果,但图简单,我就用单向破折号流程书写):
用户浏览器向APP所在的服务器发送请求-->服务器处理请求,检查确认用户请求的URL是否存在-->如果URL不存在,那么向用户浏览器发送错误信息,重新导向一个404 Not Found page-->如果URL存在,服务器执行代码并且从数据库中提取用户所需数据,在这种情况下,Django/Python代码执行查询并获取数据-->Django/Python代码将数据注入APP模板中,完成页面的HTML源码,并呈现给发出请求的用户。
进入刚才提到的“典型代表”:Basketball Reference,去John Wall的比赛记录页面(http://www.basketball-reference. ... ljo01/gamelog/2015/)查看源码。Windows下Ctrl+f,寻找任意一个日期,我们可以在源码中查获比赛记录,这个页面就是典型的server-side呈现模式,它的数据就直接展示在页面源码中。
但是,如果一个APP利用AngularJS建造出client-side,那么以上的流程就会有些许不同。服务器依旧会发送统计内容,但是HTML就仅仅是一个模板,它自身不包含任何数据,服务器响应的Javascript从一个API获取数据,并使用它来创建页面客户端。
回归昨天文章的开头内容,在NBA stats中进入John Wall的页面(http://stats.nba.com/player/#!/202322/tracking/shotslogs/),在源码中,尝试寻找“Was @”是一无所获的,虽然你可以在网页上找到许多“Was @”字符串,但是然并卵。
所以可能会认为无法在这里写爬虫了?不对,这些网站一般都有API,但是这些API都处于underlying状态,只需要明白如何去把API给挖掘出来。
Find API
在client-side APP中,浏览器承担了大部分的工作,它是HTML代码的呈现工具。我们可以用浏览器内置的开发者工具来查看数据的来源,也可以顺藤摸瓜地找到API。
以Chrome和NBA stats的网页为例,审查元素-->Network tab,里面空空如也,F5刷新后,Network里会出现如下界面。
进行XHR筛选,XHR = XMLHttpRequest,这是用来获取XML或JSON格式数据的请求,在tab里会出现很多入口。其中有一个就是返回所需数据的API。
现在需要从已有的requests中筛选出正确的。列表中的playerdashptshotlog似乎是需要的那一个。选中它后在Preview tab中可以查看其结构。
的确没有错,resource名称是{resource: "playerdashptshotlog",…},API的请求参数是parameters: {LeagueID: "00", Season: "2014-15", SeasonType: "Regular Season", PlayerID: 202322, TeamID: 0,…}。这里的parameters是形参,在编程过程中,可以改变Season、PlayerID等,传递实参,获取不同的信息。接下来的rowSet结构树内的信息就是请求的返回数据。
rowSet就是lists in a list,关于列表中每个索引值的说明,headers中已经说得相当清楚。
现在回归到Headers tab,把API复制下来。显而易见,API就是Request URL。
在新的浏览页面打开复制的API地址,可以看见寻找的数据已经转化为规整的JSON格式。
要通过挖掘出的API编写爬虫就非常easy了。用requests模块可以搞定。可以采用:
response.raise_for_status() #确定response是否有效
接下来就是自由发挥,改变实参,利用数据,比如PlayerID:201935是上一篇文章中James Harden的ID。
不同的网站API返回的结果不一样,有些是XML格式,有些是包含array/maps/dictionaries的列表。
我继续在此基础尝试了另一个美国重要的职业体育联盟:MLB(职业棒球联盟)的网站数据抓取,同样可以采用这种寻找API的方法。
最后声明:本文章来自于转载,网址为:http://luochenscorpion.lofter.com/post/1d4eebcc_803612d