抓取box.net分享连接的python脚本

通过前面写的注册机,我已经在box.net注册和上传了很多文件。

现在把自己提取分享连接的脚本发布出来。

这段脚本只是模拟各种http请求:登陆,查看文件夹,翻页,逐个分享文件,解析json

让人感觉麻烦一点是token和cookie。

token在切换文件夹的页面产生了变化,也曾让我在写代码的过程中遇到过疑惑。

Crawler类通过用户名和密码构造,login方法尝试登陆:

crawler = Crawler('your_email', 'your_password')
crawler.login()

ls方法用于列文件,必需的参数是一个文件夹名,

sorted_by参数是可选的: name, date, size

sorted_direction参数是可选的: ASC, DESC

lst_files = crawler.ls('a_folder_name', sorted_by='date', sorted_direction='ASC')

ls方法返回的是一个列表,而列表中的每个元素都是元组tuple。

这个tuple的形式是: (文件名, 分享链接)

 

这段代码的效率较低,

因为文件是逐个分享的,没有使用多线程,而http请求和解析json的次数过多。

查阅代码

 

解决python urllib2 302重定向后丢cookie的问题

通过昨天写的python脚本,我已经注册激活了50个box.net账号,用作上传文件。

今天我继续写代码,用来自动登录box.net并获取所有文件的分享链接。

不过测试的时候出现了点问题,账号信息正确,但总是登录不成功。

headers中referer、user-agent都有伪造,cookie也有发送。

通过设置debuglevel=1跟踪http请求,最终发现了问题:

        httpHandler = urllib2.HTTPHandler(debuglevel=1)
        httpsHandler = urllib2.HTTPSHandler(debuglevel=1)
        self.opener = urllib2.build_opener(httpHandler, httpsHandler)

urllib2很聪明,在发现HttpResponse中有重定向(301, 302)时会自动转向请求这个新的URL,

但urllib2有个严重的问题,它没有带着cookie去请求新的URL。

这也是说,前期我们通过一个POST请求来获取cookie(对应着服务器上的session),

但urllib2却没有带着必要的cookie去访问需要授权的页面。

一开始我是想直接用httplib的,考虑到前后一致性才全部用urllib2,结果urllib2又出问题。。。

解决这个问题,可以:

1. 换httplib来实现,它不会像urllib2会自动处理重定向,cookie不会丢

2. 截获重定向,禁止urllib2自动处理

我选择了重写urllib2.HTTPRedirectHandler的http_error_302方法,截获302,让urllib2不再处理302:

class HttpRedirect_Handler(urllib2.HTTPRedirectHandler):
    def http_error_302(self, req, fp, code, msg, headers):
        pass

然后在urllib2.build_opener方法中用HttpRedirect_Handler的一个实例做参数,例如:

self.opener = urllib2.build_opener(HttpRedirect_Handler(),
                                   urllib2.HTTPCookieProcessor(self.cookie))

这样,当我们用上述opener去POST登录时,遇到302就不会再自动转向了,

登录成功获取到的cookie也不会丢。

后面再带着self.cookie去请求需要授权的页面,就可以获取到正确的内容了。

 

批量注册Box.net账号的python脚本

国内网盘上传速度实在太慢了(跟运营商也有关系),没办法,我只好选择国外的网盘。

但国外网盘一个最大的问题是,容量小,dropbox起始2GB,而google Drive也才5GB。

最终我选择的是box.net网盘,10GB,并且外链非常容易编程获取。

web上传大约2M/s,甚至不用客户端。

如果上传500GB的文件,将需要超过50个账号,手工注册太麻烦,于是写下一小段python脚本:

1. 注册表单位于: https://app.box.com/signup/personal/

2. 在上述页面可获取request token和cookie

3. 自己构造表单信息后提交

选择批量注册,另一个比较重要的原因,是我的邮箱域设置了自动转发。

对于不存在的用户,比如[email protected], [email protected]

都将转发到一个指定的管理员邮箱,比如[email protected]

所以,所有的激活邮件都将直接发送给我自己,激活也比较方便,不用登陆不同的邮箱。

代码在这里

代码中的例子是注册[email protected][email protected]这种形式的账号。

 

最后还想说一句:屌丝用户伤不起,买个网盘都嫌贵。。。

 

一个简单的python日期字符串格式化函数

之前从豆瓣音乐上爬了大概98万个专辑,包括各个专辑的参数。

为了处理专辑的发布日期,我写了一个简单的日期格式化函数。

豆瓣音乐上的日期没有统一规范,还包含不少错误,混乱,甚至无关的文字。

但正确出现的日期字符串,则主要有这几种形式:

10 December, 1991

30 June 1992

April 13, 1999

December 1994

June, 1992

2004 03

2002年08月05日

2004年6月

2002年

我需要的最终格式是:

2013-09-15

2013-09

2013

源代码在:  https://github.com/lijiejie/format-date-str

请传入一个unicode字符串

BeautifulSoup的innerHTML实现

innerHTML方法用于提取某个标签内部的HTML内容,多数HTML Parser都实现了该方法。

BeautifulSoup暂未提供innerHTML方法,但我们可以通过遍历子元素并拼接html来实现它。

例如,我需要获取豆瓣音乐上某个专辑的描述信息,它位于一个id为info的div中。

参考:http://music.douban.com/subject/1394539/

我需要图示部分的html代码:

info-div

这时只需要一行代码:

album_info = u''.join([unicode(x) for x in soup.find('div', id='info').contents]).strip()

值得注意的是,豆瓣音乐的网页编码是utf8,需要先decode utf8再parse。

而在Beautiful内部,所有对象都是unicode object。

contents属性返回所有child element的列表。

因为我是在windows中文版的系统下写这段脚本,当需要在命令提示符下输出内容的时候,还必须先encode gbk。

print album_info.encode('gbk', 'ignore')

 

参考链接:

http://stackoverflow.com/questions/8112922/beautifulsoup-innerhtml

扫描"豆瓣音乐"所有专辑的简单Python脚本

我需要一些音乐数据,而 豆瓣音乐 上相关数据是非常齐全的。

即使是十分小众、鲜有人听过的专辑,豆瓣也提供了较为详细的描述。

摆在我面前的第一个问题是,如何将豆瓣音乐上的专辑一网打尽,一个不遗漏地抓取到。

我们观察某个专辑的页面: http://music.douban.com/subject/1415369/

看到subject后跟着一串数字ID,这时候一个简单的思路已经出来了:

将id从1不断递增,扫描完所有的ID,检查哪些ID是存在的

又观察到大多数专辑页面上存在相关推荐,也就是那个“喜欢某某专辑的人也喜欢… …”。

这里存在一对N的超链接映射,最终形成了网络,于是可以有第二个思路:

将某个专辑加入队列,从它出发,通过 “也喜欢” 来获取新专辑,并将这些新专辑加入队尾

每完成一次操作,就从队列中删除队首的专辑

循环上面的过程,直到处理完队列中的所有元素

最终获取到的就是包含第一个元素的网

当然,上面的思路是有缺陷的,那些孤立的专辑无法被包括进来。

继续阅读扫描"豆瓣音乐"所有专辑的简单Python脚本