目录
一、定义三个函数方便之后调用
1.由url获取soup函数
2.传入soup,进具体信息进行解析
3.由图片链接保存到本地
二、生产-消费主模块(精华部分)
1.获取一个分类下的所有歌单的id,相当于生产者
2.对每个id,获取歌单的详细信息,相当于消费者
三、主要代码展示
def get_soup(url):'''传入url,得到soup库解析后的结果'''response = requests.get(url)html = response.textsoup = BeautifulSoup(html, 'html.parser')return soupdef parsing_information(ids,soup,count):'''传入上一节的解析内容,对具体信息进行解析'''# 获取歌单标题,替换英文分割符title = ids[count]['title'].replace(',', ',')# 获取歌单idid = ids[count]['href']#获取创建者昵称nickname = soup.select('.s-fc7')[0].get_text()#获取介绍description = soup.select('p')[1].get_text()#获取歌曲数量song_num = soup.select('span span')[0].get_text()#获取播放量play_num = soup.select('strong')[0].get_text() #获取分享次数share_num = soup.select('a i')[2].get_text() #获取评论次数comment_num = soup.select('a i')[4].get_text() #评论次数list1 = [title,id,nickname,description,song_num,play_num,share_num,comment_num]return list1def save_picture(soup):'''这是一个传入soup,保存照片到路径的函数'''lis = soup.select('#m-playlist')img_url = lis[0].select('.j-img')[0]['data-src']img = requests.get(url=img_url)name_id = str(random.random())if os.path.exists(r'E:/学习文件/大三上/现代程序设计/第十二次作业/图片/' + name_id) == False:os.mkdir(r'E:/学习文件/大三上/现代程序设计/第十二次作业/图片' + name_id)f = open('E:/学习文件/大三上/现代程序设计/第十二次作业/图片/' + name_id + + ".jpg", "wb")f.write(img.content)f.close()
传入的q是多线程中使用的队列,函数末尾使用put()函数传入
def producer(q,url): soup = get_soup(url)# 获取包含歌单详情页网址的标签#对dec a的class进行选择ids = soup.select('.dec a')q.put(ids)
def consumer(q):row_topname = ['歌曲标题','id','昵称','简介','歌曲数量','播放量','分享次数','评论次数']file = open('playlist.csv', 'w', encoding='utf-8')csv_writer = csv.writer(file) #csv格式写入文件filecsv_writer.writerow(row_topname)ids = q.get()count = 0for id in ids:url = 'https://music.163.com/' + id['href'] #生产者传递的id链接soup = get_soup(url)#使用自定义的解析函数,返回信息列表list1 = parsing_information(ids, soup, count)#使用自定义的图片保存函数save_picture(soup)#写入信息进csv文件csv_writer.writerow(list1)count = count + 1 #计数器file.close()
def get_soup(url):'''传入url,得到soup库解析后的结果'''response = requests.get(url)html = response.textsoup = BeautifulSoup(html, 'html.parser')return soupdef parsing_information(ids,soup,count):'''传入上一节的解析内容,对具体信息进行解析'''# 获取歌单标题,替换英文分割符title = ids[count]['title'].replace(',', ',')# 获取歌单idid = ids[count]['href']#获取创建者昵称nickname = soup.select('.s-fc7')[0].get_text()#获取介绍description = soup.select('p')[1].get_text()#获取歌曲数量song_num = soup.select('span span')[0].get_text()#获取播放量play_num = soup.select('strong')[0].get_text() #获取分享次数share_num = soup.select('a i')[2].get_text() #获取评论次数comment_num = soup.select('a i')[4].get_text() #评论次数list1 = [title,id,nickname,description,song_num,play_num,share_num,comment_num]return list1def save_picture(soup):'''这是一个传入soup,保存照片到路径的函数'''lis = soup.select('#m-playlist')img_url = lis[0].select('.j-img')[0]['data-src']img = requests.get(url=img_url)name_id = str(random.random())if os.path.exists(r'E:/学习文件/大三上/现代程序设计/第十二次作业/图片/' + name_id) == False:os.mkdir(r'E:/学习文件/大三上/现代程序设计/第十二次作业/图片' + name_id)f = open('E:/学习文件/大三上/现代程序设计/第十二次作业/图片/' + name_id + + ".jpg", "wb")f.write(img.content)f.close()def producer(q,url): soup = get_soup(url)# 获取包含歌单详情页网址的标签#对dec a的class进行选择ids = soup.select('.dec a')q.put(ids) def consumer(q):row_topname = ['歌曲标题','id','昵称','简介','歌曲数量','播放量','分享次数','评论次数']file = open('playlist.csv', 'w', encoding='utf-8')csv_writer = csv.writer(file) #csv格式写入文件filecsv_writer.writerow(row_topname)ids = q.get()count = 0for id in ids:url = 'https://music.163.com/' + id['href'] #生产者传递的id链接soup = get_soup(url)#使用自定义的解析函数,返回信息列表list1 = parsing_information(ids, soup, count)#使用自定义的图片保存函数save_picture(soup)#写入信息进csv文件csv_writer.writerow(list1)count = count + 1 #计数器file.close()
if __name__ == '__main__':url_list = []plist,clist = [],[]q = Queue()for n in range(0,1355,35):url = f'https://music.163.com/discover/playlist/?order=hot&cat=%E8%AF%B4%E5%94%B1&limit=35&offset={n}'url_list.append(url)for url in url_list:p = Thread(target=producer,args=(q,url,))plist.append(p)for p in plist: p.start()for t in plist:p.join()for i in range(100): c = Thread(target=consumer,args=(q,))clist.append(c)for c in clist: #启动线程c.start()for c in clist:q.put(None)