selenium + phantomjs 爬取落网音乐

题记:

  作为一个业余程序猿,最大的爱好就是电影和音乐了,听音乐当然要来点有档次的。落网的音乐的逼格有点高,一听听了10年。学习python一久了,于是想用python技术把落网的音乐爬下来随便听。

目的:

  将每一期的落网音乐下载到电脑上。

=====================================================================================

版本一:

  刚开始,学习了爬虫技术中的urllib,urllib2,httplib,然后学习了用requests + beautifulsoup获取数据(python理念:能简单为啥还要复杂)。

于是,就有了这个版本。

图1:

  

图2:

  

 

图3:

  

 

缺点:

  1、从html元素查找title,再从request请求查看每一首音乐的url,这个半手动的违背了自动下载的初衷。

  2、这个音乐url是规律的命名,如果不规律的话,便不能用了。

  3、单线程下载,速度慢。

需要改进的地方:

  1、音乐url应能自动在网页里搜索,而不需要手动查看request请求的header。

  2、使用多线程。提高下载速度。

=================================================================

版本二:

分析:

  1、打开落网每一期音乐的页面,查看源代码中,不能看到音乐的url,那判定该音乐是由js发起的请求。

  2、要查看web页面中js发起的请求时,用requests模块只能获取静态的url,如果是动态的就没办法了。

  3、通过搜索查阅,找到一款神器,selenium + phantomjs。

    selenium是web自动化测试包,测试直接运行在浏览器中,就像真正的用户在操作一样,详见官网 http://www.seleniumhq.org。

    phantomjs是基于webkit的javascript API,可以编译解释执行JavaScript代码。详见:官网 http://phantomjs.org。

    webdriver api 见 http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.remote.webdriver。

  4、Time fly,just do it。

  在分析过程中,开始一直是requests模块的思维,由于落网的js是压缩过的,想到解压js,再查找相关的dom元素,再进行webElement的click提交,查看请求,但是这种方法一直没有结果。用了chrome 及 opera 的开发者工具,仍然无果。

  换个思路,用了firefox的firebug试试。打开页面后,发现这个东西:

  

  看了看内容,这就是js对象呀。再仔细查看,找到了这个:

  

   

  哎哟,这不就是我要找的东西么,真是破铁鞋无觅处、得来全不费工夫呀。。。

  但是,如果通过代码得到这个东西呢,一直没想到好的办法(业余菜鸟,对http请求了解太少)。

  偶然看到这篇帖子:http://blog.csdn.net/pushiqiang/article/details/51290509

  里面有一句代码得到启发:

  

  这是返回js变量,那我需要的代码变量应用就是firebug里的luooPlayer了。

  测试:

  

  得到结果:

  

  终于,主要的内容搞定。那接下来就是download每一期了,再加上多线程,就能下载了。

代码:

 1 #coding:utf-8
 2 '''
 3 Auth:daivlin
 4 Date:2016-12-22
 5 '''
 6 
 7 import os
 8 import time
 9 import urllib
10 import threading
11 from selenium import webdriver
12 
13 class Luoo(object):
14     def __init__(self,issue):
15         ''' init ,参数为期数 '''
16         self.issue_url = r"http://www.luoo.net/music/" + "%03d"%issue
17         driver = webdriver.PhantomJS()
18         driver.get(self.issue_url)
19 
20         #每期名称如: VOL666 欢迎来到巴黎
21         self.issue_name = "VOL." + "%03d"%issue + " " + driver.title
22         luooPlayer = driver.execute_script("return luooPlayer") #读取js变量
23 
24         #音乐列表为元组:(name,url)
25         self.music_list = []
26         var = 1
27         for i in luooPlayer["playlist"]:
28             self.music_list.append(("%02d"%var,i["mp3"]))
29             var += 1
30         driver.quit()
31 
32     def get_issue_name(self):
33         ''' 获取期刊号 '''
34         return self.issue_name
35 
36     def get_music_list(self):
37         ''' 获取音乐列表 '''
38         return self.music_list
39 
40 class DownloadThread(threading.Thread):
41     ''' 下载线程'''
42     def __init__(self,dirname,name,url):
43         super(DownloadThread,self).__init__()
44         self.dirname = dirname
45         self.name = name
46         self.url = url
47 
48     def run(self):
49         ''' 下载音乐 '''
50         ABSPATH = os.path.dirname(os.path.realpath(__file__))
51         DOWNDIR = os.path.join(os.path.join(ABSPATH,"Luoo"),"%s"%self.dirname)
52         MUSICPATH = os.path.join(DOWNDIR,"%s.mp3"%self.name)
53         try:
54             os.mkdir(DOWNDIR)
55         except:
56             pass
57         if not os.path.exists(MUSICPATH):
58             urllib.urlretrieve(self.url, MUSICPATH)
59             print "%s.mp3 was downloaded"%self.name
60 
61 for i in range(867,888):
62     r = Luoo(i)
63     name = r.get_issue_name()
64     tds = []
65     for j in r.get_music_list():
66         tds.append(DownloadThread(name,j[0],j[1]))
67     print "start download %s"%name
68     for td in tds:
69         td.start()
70     for tj in tds:
71         tj.join()
72     print "%s download complate"%name
73     print "========================="
74 
75 print "All have downloaded"

 下载效果:

  

待改进的地方:

  1、因为编码问题报错,文件名称用序号代替,需改为真实音乐名称。

==============================================================================

webdriver执行js代码,得到返回的值代码如下:

jscode = '''
            var img_src = $("img.vol-cover");
            return img_src.attr("src");
        '''
img_cover = driver.execute_script(jscode)

 

==============================================================================

  爬虫只供参考

  做个厚道的程序猿

  别增加人家的服务器压力

==============================================================================

  人生苦短,我用python!

 

posted @ 2016-12-22 21:11  daivlin  阅读(267)  评论(0编辑  收藏  举报