我需要一些音乐数据,而 豆瓣音乐 上相关数据是非常齐全的。
即使是十分小众、鲜有人听过的专辑,豆瓣也提供了较为详细的描述。
摆在我面前的第一个问题是,如何将豆瓣音乐上的专辑一网打尽,一个不遗漏地抓取到。
我们观察某个专辑的页面: http://music.douban.com/subject/1415369/
看到subject后跟着一串数字ID,这时候一个简单的思路已经出来了:
将id从1不断递增,扫描完所有的ID,检查哪些ID是存在的
又观察到大多数专辑页面上存在相关推荐,也就是那个“喜欢某某专辑的人也喜欢… …”。
这里存在一对N的超链接映射,最终形成了网络,于是可以有第二个思路:
将某个专辑加入队列,从它出发,通过 “也喜欢” 来获取新专辑,并将这些新专辑加入队尾
每完成一次操作,就从队列中删除队首的专辑
循环上面的过程,直到处理完队列中的所有元素
最终获取到的就是包含第一个元素的网
当然,上面的思路是有缺陷的,那些孤立的专辑无法被包括进来。
我决定使用ID自增的方式来扫专辑。
在python中,直接使用urllib2.urlopen去下载完整的HTML页面是不太经济的,
特别是一开始我并不需要解析HTML,我只是想知道这个页面是否存在。可以使用head请求。
我还观察到直接访问www.douban.com/subject/id可能会产生一个302的重定向,或者404错误
比如访问 http://www.douban.com/subject/1415369/, 会302重定向到
http://music.douban.com/subject/1415369/
于是我可以通过请求www.douban.com/subject/id/来确定对应ID是否是一个音乐专辑的ID
302还可能是重定向到其他douban.com二级域名,比如book、movie,但我只需要music,其他的直接忽略了。
(获取豆瓣所有的电影和图书也很方便,不是吗?)
MySQL下创建表album:
CREATE TABLE `album` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`album_url` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_album_id` (`album_url`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
它包括id字段和album_url字段,但album_url是int,并非varchar,因为我只需要保存数字id。
完整的源代码,请参考: https://github.com/lijiejie/scan-douban-ids
这里有一点小的技巧:
- headers伪装成了goolebot,减小IP被屏蔽的几率
- id从1扫描到3000万,这是个估值上界,通过查看豆瓣最近收录的新专辑判断
- 同步队列id_queue最大的长度是100,不要忽略了参数,设置成无限长度,3000万太多
- 这里有50个线程同时工作,但是数据库连接dbconn是全局的、公用的,使用锁lock来确保每次只有一个线程进入
- 在id_queue中加入了50个None,作为结束标志
- 可以直接HEAD请求music.douban.com的页面判断是否存在,404表示这个id不存在、302表示这个id是其他内容而不是音乐,只有status返回200才表示对应的专辑存在
使用上面的脚本,从昨晚运行到现在,我已经扫描到了70万个专辑。 🙂
单引号目测是中文格式的。。。
标题那个吗? 现在的其实是英文双引号,可能因为字体原因,看起来有点别扭。 中文的是那种带长尾巴的
换了个英文全角的双引号。。 之前那个是半角的。 谢谢提醒
额,其实我说的是mysql那段代码里的单引号啊。
那个是反引号吧
学习了!
哈,松哥,有时间我们一起做些有意思的东西啊。
嗯,行啊,python有空一直再看,不过实践还是太少
好奇博主拿到所有专辑干什么用
最近几天在准备做一个音乐资源方面的网站。 可以用爬虫去爬几十万个专辑下来,版权是个问题。所以最终是否提供打包下载功能,我还在权衡。
一般私底下传播点盗版专辑,问题不大,但量大了,公开传播,会越线的。
加锁是一个瓶颈,多线程50个也是一个瓶颈,我觉得使用无锁数据结构,加上内存缓存,以及,client端按照事件驱动的方式进行设计性能会非常好,几个核就起几个进程。进程之间独立,将搜索的数据区间分段到每个独立绑定到核上的进程。
膜拜搞后台开发的大牛。。。 算法和设计模式方面,我确实非常欠缺。 Python的多线程好像确实不能充分利用多核。
可以试试用Erlang语言改写
没写过erlang,最近似乎Go语言非常火。
根据我写爬虫的一年经验,很多时候cpu不是瓶颈
是的,我自己感觉甚至网络都难以成为瓶颈。我这边12M的ADSL,跑满了可以达到1.4M/s左右。数据库操作确实会成为瓶颈,如果得不到好的优化。其实前几天我也正想向你求助MySQL的优化。有一个表album目前已经有超过100万条记录,表的大小也接近1GB了。有机会了向你求教一下。
目前我们有很多数据库都超过100w记录,变动大的数据和变动小的基本上都分离开来,优化索引足够小常驻内存。超过1亿条记录的基本不怎么建索引,只做顺序读取。
这个怎么用,向高人请教!
这个程序当初是用模拟按键来批量注册360云盘的。
不确定现在还能否使用。
对的啊!现在问题是我把路径修改到我电脑里安装的云盘客户端位置,只能打开!点击注册没反因阿~不知道是不是保存在哪了?
还有那个1-100是什么意思?写a-z是不也可以
这个程序时间有点长了,没有更新维护过,恐怕是已经失效了。再者现在360云盘似乎是可以免费增加到36TB的,应该不需要注册那么多了。
你会改软件吗?
http://down.jinlansoft.com/download/360账号注册机.rar想让你帮我把登陆框去掉~~
之前也写过一个爬豆瓣专辑的虫子,通过api调用有每分钟40个查询的限制。看见你模拟googlebot,好用么?
访问过程没出现什么限制。
学长 这个 完整的源代码,请参考: https://github.com/lijiejie/scan-douban-ids
现在无法获取了 是不是因为涉及到非法抓取数据 你担心越线 删除了?
真想研究一下你的源码 可惜现在没了 你能给私下发一下吗?
我的邮箱:[email protected]