100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > python爬虫第二弹-多线程爬取网站歌曲

python爬虫第二弹-多线程爬取网站歌曲

时间:2021-10-08 09:41:22

相关推荐

python爬虫第二弹-多线程爬取网站歌曲

python爬虫第二弹-多线程爬取网站歌曲

一、简介二、使用的环境三、网页解析1、获取网页的最大页数2、获取每一页的url形式3、获取每首歌曲的相关信息4、获取下载的链接四、代码实现

一、简介

近日,迷惑墙报道了一个神奇的网站,网站域名为,没错,就是ustcnet…访问网站之后发现,该网站的ustc实际上是指Unexceptionable Songs Taken from Cartoon,看到这么多好听的动漫歌曲并且可以直接下载,肥宅病顿时复发了😆😆😆,博主遂决定写一个爬虫来批量下载所有的歌曲,以作收藏。遗憾的是,该网站从开始已经停更了,所以内容较少。

二、使用的环境

python3.9.0re库(正则表达式)requests库(请求特定网页)threading库(多线程爬取,加快速度)bs4库(主要使用BeautifulSoup解析网页结构)

三、网页解析

1、获取网页的最大页数

在网站主页最底部可以看到,会显示网站的最大页数以及当前页数,因此可以在源码中找到这些信息。点击鼠标右键查看网页源代码,ctrl+F搜索“/2",就能在网页源码中找到该位置。如图:

有了这一信息之后,就可以使用正则表达式在获取到的网页源码文本中搜索相关信息,从而找到最大页面,使用的表达式是:

pattern=pile(r'(?<=</b></font>/)\d+')

其中表达式(?<=exp)表示的是先定位到exp表达式的位置,然后从后面开始匹配,\d+表示匹配1到多个数字,满足贪婪匹配。然后通过该表达式对获取的网页源码进行匹配,就能够得到最大页数。

2、获取每一页的url形式

在主页上点击下一页,可以很容易地发现网站每一页网页的形式为:

'/index.asp?page={}'.format(page_count)

同时有了最大页数,就可以批量生成网站每一页地url,然后对每页进行访问提取需要的信息。

3、获取每首歌曲的相关信息

通过网页调试工具发现,网页每一首歌曲的信息存放在一条tr标签中,同时可以根据标签的onmouseover属性来定位这一标签。

每个tr标签中包含一系列td标签,第2、3、4个td标签分别存储了歌曲的歌曲名、歌曲出处和歌手。

有了这些信息之后,就可以通过BeautifulSoup查找这些标签,从而获取这些信息,用于文件的命名。

4、获取下载的链接

通过网页调试工具发现,歌曲的下载链接存放在target属性为_blank的a标签中,因此获得了这一链接之后就可以批量生成每一首歌曲的下载链接。

这里还有一个小插曲,点进去这个链接之后不是直接下载,而是跳到了一个新的页面,如图,在这个页面中的a标签存放着歌曲下载的正确的url。

四、代码实现

import reimport requestsimport threadingfrom bs4 import BeautifulSoupdef GetHtmlText(url):# 根据传入的url请求网站,并返回得到的数据try:user_agent = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'}rspon = requests.get(url, headers = user_agent)rspon.encoding = 'GBK' #这里需要使用GBK编码,否则文字会出现乱码rspon.raise_for_status()except:print('网页获取失败:', rspon.status_code)return Nonereturn rspondef GetMaxPageCount():# 获取主页信息,并且获取网站的最大页数max_page_count = 0url = '/'html=GetHtmlText(url)if html==None:return max_page_count#print(html.text)pattern=pile(r'(?<=</b></font>/)\d+') #正则表达式匹配最大页数match=pattern.search(html.text)max_page_count=int(match.group(0))return max_page_countdef SaveSongInUrl(song_url,song_name,song_path):# 根据传入的url链接获取歌曲的二进制数据,并且根据传入的路径和文件名将文件写入到对应的路径中。source = GetHtmlText(song_url)if source == None:returnfile_name = '{}.wma'.format(song_name)file = open(song_path+file_name, "wb") #以二进制写的方式打开文件。file.write(source.content)#由于歌曲是以二进制存储的,这里需要写入二进制数据file.close()def GetOnePageSong(page_count, song_path):# 从返回的网页数据中获取每张图片的相关信息以及图片下载的url,然后调用相关函数下载图片url = '/index.asp?page={}'.format(page_count)suop = BeautifulSoup(GetHtmlText(url).text, 'html.parser')tag_container = suop.find_all('tr', {'onmouseover':'this.style.backgroundColor=\'#eeeeee\''}) #搜索存放每首歌曲信息的tr标签thread_list=[] #存放所有下载线程的列表for child in tag_container:tag_song_inf=child.find_all('td') #获取歌名、出处和歌手信息song_number=tag_song_inf[0].stringsong_name=tag_song_inf[1]['title'] #第一个td标签存放歌名song_from=tag_song_inf[2]['title']#第二个td标签存放出处song_sing=tag_song_inf[3].string #第三个td标签存放歌手file_name=song_name+'_'+song_from+'_'+song_sing #将以上信息拼接成歌曲名tag_download=child.find('a',{'target':'_blank'}) #查找存放下载链接的a标签download_url='/'+tag_download.attrs['href']target_soup=BeautifulSoup(GetHtmlText(download_url).text, 'html.parser')target_a=target_soup.find('a')if target_a==None:continuetarget_url=target_a.attrs['href']t=threading.Thread(target=SaveSongInUrl,args=(target_url,file_name,song_path)) #创建一个歌曲下载的线程t.start()thread_list.append(t)print('page:{}\tnumber:{}\tthreading num:{}\tis downloading...'.format(page_count,song_number,len(thread_list)))alive_thread_count=len(thread_list) #保存当前存活的线程数while alive_thread_count>5:#最大运行线程数不大于5,否者循环直到当前线程数为5for i in thread_list:if not i.is_alive():alive_thread_count-=1thread_list.remove(i)print('{} downloading threading remain...'.format(alive_thread_count))#函数退出之前保证所有线程结束alive_thread_count=len(thread_list)while alive_thread_count>0:for i in thread_list:if not i.is_alive():alive_thread_count-=1thread_list.remove(i)print('{} downloading threading remain...'.format(alive_thread_count))def GetAllPageSong(song_path):# 爬取所有页面的歌曲,并保存在输入的参数路径下max_page_count = GetMaxPageCount()for page_index in range(1, max_page_count+1):GetOnePageSong(page_index, song_path)def main():song_path='E:/ustcnetsong/'GetAllPageSong(song_path)main()

运行发现有些歌曲下载时会出现404错误,访问网站发现是由于网站本身的原因。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。