这两天一直在捣鼓这个东东,终于弄得差不多能用了。
目的:youtube网站在每一个视频的网页上,在视频的右下角,都有一个"Show video statistics"的方格子按钮,点击这个按钮,就会弹出一张图,显示本视频的历史浏览数据图。要的就是这个图背后的数据。
困难:这个图的数据并不直接储存在本视频网页的源代码里面,所以不能采取解析网页的方式直接获得。
分析:当用户点击这个按钮时,网页上的某个java script函数会被激活,youtube的服务器向当前网页发送数据,这个数据先是被浏览器读取下载,又被传送到google画图API接口,被渲染成一张曲线图后传回来。很复杂吧?
简单来说,就是要激活按钮背后隐藏的函数,才能使浏览器获得数据。
解决:调用win32com这个包,使用python命令控制IE浏览器与网页进行交互。所谓交互,就是去点击那个按钮,对于对方服务器来说,他不管对方是人还是别的什么东西,只要有点击行为,就开始传输数据,等到浏览器把数据下载完,使用python把整个网页保存成字符,剩下的就是使用正则表达式从字符中提取需要的信息这个老工作了。
目前代码的功能描述:大概功能如上所述,不过我想要分析的是用户而不是单个视频(社会科学研究一般,只要有条件的话,会把unit of analysis定为个体),所以我想要这样一个函数:输入一个用户id,可以得到这个用户上传的所有视频的url,然后对每个url,获取本视频从上传到数据抓取时间的历史观看记录增长。解决方法是我先调用了youtube提供的API,它提供了这样一个选择,可以反回该用户所有上传视频url,然后对每个url做之前描述的工作就可以了。
局限:对于每个视频,不管已经上传了多少天,狡猾的youtube最多只返回100个数据点,这意味着要进行后期处理,使用回归方程预测或者移动平均等方式填补缺失数据,因为这个部分要使用较为复杂的统计函数,我可能会用R或者mathematica来做,就不写在代码里了。另外,如果一个视频被作者声称了版权,youtube就不会公开浏览历史记录。
在写代码过程中遇到的印象比较深刻的问题(我个人觉得这一部分很重要,大家以后分享自己的工作,如果愿意的话,也可以讲讲这个):
1. 一开始google的时候有人建议用pamie或者mechanize包来模拟浏览器,但我试验后发现这两个玩意并不能解决我的问题。pamie上手特别快,命令非常简单,例如实现提交用户登录信息,返回google查询结果等非常好用,但是不知道为什么其中的button.click()函数对youtube的查看历史数据按钮不起作用。而mechanize不是与网页进行交互,而是直接调用要激活的java script那个函数,把参数给它填上,然后发送给服务器,这个方法好像听上去比较犀利一些,但对于我目前的水平有点太难了,因为要对java script语言比较了解才可以,所以我放弃了。
通过这次写代码,我总结出来抓动态网页数据的三种方法,按效率从高到低排列如下:
(1)直接找到对方服务器存储数据的html或者xml。
这是效率最高的,但要看运气和分析网页的水平,像之前我在邮件组里发的从alexa上抓取流量数据的代码,里面其实就利用了这个方法。本来网站的点击流关系是要用户把鼠标移到某个按钮上才弹出来的,也就是说,和本案例一样并不在当前url,但服务器存储点击流关系的url却隐藏在源代码一个非常不起眼的地方,直接连上了这个url就好办了。这还得感谢我的朋友,城大计算机搞IR的SJF同学,是他看过网页后告诉我这个url的。但是,如果你像我一样水平比较低,找不到这个url,或者是人品不好遇上了youtube这种网站,根本不在源代码里存储这个url,那就只能绕行了。
(2)使用mechanize这种东西,代替浏览器给服务器发请求,然后抓数据。利与弊前面已经说了。
(3)调用IE,firefox等浏览器,模拟点击,然后坐等数据。利与弊前面也已经说了。相对来说,这是比较粗暴,但容易实现的一种方法。不需要靠人品,也不需要很高的水平,很robust,英雄特纳奈尔,一定会实现。网络爬虫抓取网页数据,听起来很神秘,其实很简单。其实就是相当于你雇佣了很多小TA,给你一个一个地打开,复制,存储网页(我的一些朋友,真的干过这件事)。有钱你就雇用TA,没钱你还是学着写程序吧。
2. 模拟浏览器的函数,原来逐行运行的时候都没问题,后来发现组装成函数,就是返回空集。后来才发现,原来是没给浏览器喘口气的时间,当程序模拟点击之后,我不能马上抓数据,因为浏览器要喘口气才能把数据从服务器下载下来,所以加了time.sleep(2)这个命令,意思就是说程序你睡两秒钟,等浏览器拿到数据了我们再抢劫。这就行了
对本程序有贡献的人士:之前一直想要搜集一个互联网资源,例如一个博客或者一个视频,它的点击随时间变化的数据,但这种数据太少了。chengjun给我看一篇很好的论文,里面提到youtube有这个数据,虽然我们看到的是图,其实网页里有数据。linwu在我们实验室访问时展示了如何使用java代码制造模拟浏览器搜集新浪博客的评论数据,并且慷慨无私地把代码拷给我,让我了解了模拟浏览器基本的代码构造,启发了我使用python做类似事情的思路。
最后,现在这个代码和之前从alexa上抓点击流的代码,以后我应该会开源,但因为涉及我博士论文的研究,在我毕业之前,请大家先不要post到别的地方去。
先写这些吧。一如既往,欢迎交流。
--
Wu Lingfei
wlf8...@gmail.com
Dept. of Media & Communication
City University of Hong Kong