selenium + phantomjs 爬取落网音乐

时间:2022-03-16 05:04:54

题记:

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

目的:

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

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

版本一:

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

于是,就有了这个版本。

图1:

  selenium + phantomjs 爬取落网音乐

图2:

  selenium + phantomjs 爬取落网音乐

 

图3:

  selenium + phantomjs 爬取落网音乐

 

缺点:

  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试试。打开页面后,发现这个东西:

  selenium + phantomjs 爬取落网音乐

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

  

   selenium + phantomjs 爬取落网音乐

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

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

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

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

  selenium + phantomjs 爬取落网音乐

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

  测试:

  selenium + phantomjs 爬取落网音乐

  得到结果:

  selenium + phantomjs 爬取落网音乐

  终于,主要的内容搞定。那接下来就是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"

 下载效果:

  selenium + phantomjs 爬取落网音乐

待改进的地方:

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

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

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

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

 

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

  爬虫只供参考

  做个厚道的程序猿

  切勿增加人家的服务器压力

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

  人生苦短,我用python!