t_div.find('ul', class_='songlist__list')
18 lis = songlist_ul.find_all('li')
19 del lis[0] # 删除第一个li
20 # print('len(lis):$s' % len(lis))
21 for li in lis:
22 a_songname_txt = li.find('div', class_='songlist__songname').find('span', class_='songlist__songname_txt').find('a')
23 if 'https' not in a_songname_txt['href']: #如果单曲链接不包含协议头,加上
24 song_url = 'https:' + a_songname_txt['href']
25 song_name = a_songname_txt['title']
26 singer_name = li.find('div', class_='songlist__artist').find('a').get_text()
27 song_time =li.find('div', class_='songlist__time').get_text()
28 music_info = {}
29 music_info['song_name'] = song_name
30 music_info['song_url'] = song_url
31 music_info['singer_name'] = singer_name
32 music_info['song_time'] = song_time
33 collect_data(music_info)
34 except Exception as err: # 如果解析异常,跳过
35 print('Downloading or parse music information error continue:', err.args)
4.执行爬虫
爬虫跑起来了,一页一页地去爬取专辑的链接,并保存到集合中,最后通过get_music()方法获取单曲的名称,链接,歌手名称和时长并保存到Excel文件中。
三、Python爬取QQ音乐单曲总结
1.单曲采用的是分页方式,切换下一页是通过异步ajax请求从服务器获取json格式的数据并渲染到页面,浏览器地址栏链接是不变的,不能通过拼接链接来请求。一开始想过都通过Python Urllib库来模拟ajax请求,后来想想还是用Selenium。Selenium能够很好地模拟浏览器真实的操作,页面元素定位也很方便,模拟单击下一页,不断地切换单曲分页,再通过BeautifulSoup解析网页源码,获取单曲信息。
2.url链接管理器,采用集合数据结构来保存单曲链接,为什么要使用集合?因为多个单曲可能来自同一专辑(专辑网址一样),这样可以减少请求次数。
1 class UrlManager(object):
2 def __init__(self):
3 self.new_urls = set() # 使用集合数据结构,过滤重复元素
4 self.old_urls = set() # 使用集合数据结构,过滤重复元素
5 def add_new_url(self, url):
6 if url is None:
7 return
8 if url not in self.new_urls and url not in self.old_urls:
9 self.new_urls.add(url)
10
11 def add_new_urls(self, urls):
12 if urls is None or len(urls) == 0:
13 return
14 for url in urls:
15 self.add_new_url(url)
16
17 def has_new_url(self):
18 return len(self.new_urls) != 0
19
20 def get_new_url(self):
21 new_url = self.new_urls.pop()
22 self.old_urls.add(new_url)
23 return new_url
3.通过Python第三方插件openpyxl读写Excel十分方便,把单曲信息通过Excel文件可以很好地保存起来。
1 def write_to_excel(self, content):
2 try:
3 for row in content:
4 self.workSheet.append([row['song_name'], row['song_url'], row['singer_name'], row['song_time']])
5 self.workBook.save(self.excelName) # 保存单曲信息到Excel文件
6 except Exception as arr:
7 print('write to excel error', arr.args)
四、后语
最后还是要庆祝下,毕竟成功把QQ音乐的单曲信息爬取下来了。本次能够成功爬取单曲,Selenium功不可没,这次只是用到了selenium一些简单的功能,后续会更加深入学习Selenium,不仅在爬虫方面还有UI自动化。
后续还需要优化的点:
1.下载的链接比较多,一个一个下载起来比较慢,后面打算用多线程并发下载。
2.下载速度过快,为了避免服务器禁用IP,后面还要对于同一域名访问过于频繁的问题,有个等待机制,每个请求之间有个等待间隔。
3. 解析网页是一个重要的过程,可以采用正则表达式,BeautifulSoup和lxml,目前采用的是BeautifulSoup库, 在效率方面,BeautifulSoup没lxml效率高,后面会尝试采用lxml。