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

一、简介

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

二、使用的环境

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

三、网页解析

1、获取网页的最大页数

在网站主页最底部可以看到,会显示网站的最大页数以及当前页数,因此可以在源码中找到这些信息。点击鼠标右键查看网页源代码,ctrl+F搜索“/2",就能在网页源码中找到该位置。如图:
在这里插入图片描述
有了这一信息之后,就可以使用正则表达式在获取到的网页源码文本中搜索相关信息,从而找到最大页面,使用的表达式是:

pattern=re.compile(r'(?<=</b></font>/)\d+')

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

2、获取每一页的url形式

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

'http://www.ustcnet.com/index.asp?page={}'.format(page_count)

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

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

通过网页调试工具发现,网页每一首歌曲的信息存放在一条tr标签中,同时可以根据标签的onmouseover属性来定位这一标签。
在这里插入图片描述
每个tr标签中包含一系列td标签,第2、3、4个td标签分别存储了歌曲的歌曲名、歌曲出处和歌手。
在这里插入图片描述
有了这些信息之后,就可以通过BeautifulSoup查找这些标签,从而获取这些信息,用于文件的命名。

4、获取下载的链接

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

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

在这里插入图片描述

四、代码实现

import re
import requests
import threading
from bs4 import BeautifulSoup

def 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 None
    return rspon

def GetMaxPageCount():
    # 获取主页信息,并且获取网站的最大页数
    max_page_count = 0
    url = 'http://www.ustcnet.com/'
    html=GetHtmlText(url)
    if html==None:
        return max_page_count
    #print(html.text)
    pattern=re.compile(r'(?<=</b></font>/)\d+')    #正则表达式匹配最大页数
    match=pattern.search(html.text)
    max_page_count=int(match.group(0))
    return max_page_count

def SaveSongInUrl(song_url,song_name,song_path):
    # 根据传入的url链接获取歌曲的二进制数据,并且根据传入的路径和文件名将文件写入到对应的路径中。
    source = GetHtmlText(song_url)
    if source == None:
        return
    file_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 = 'http://www.ustcnet.com/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].string
        song_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='http://www.ustcnet.com/'+tag_download.attrs['href']
        target_soup=BeautifulSoup(GetHtmlText(download_url).text, 'html.parser')
        target_a=target_soup.find('a')
        if target_a==None:
            continue
        target_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,否者循环直到当前线程数为5
            for i in thread_list:
                if not i.is_alive():
                    alive_thread_count-=1
                    thread_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-=1
                thread_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错误,访问网站发现是由于网站本身的原因。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您介绍一下如何使用 Python 爬虫爬取房产数据并保存到本地。 首先,您需要选择一个合适的网站来进行爬取。例如,可以选择链家网、安居客等房产网站。然后,您需要分析该网站的页面结构和数据请求方式,确定需要爬取哪些数据,以及如何获取这些数据。 接着,您可以使用 Python 的 requests 库来发送 HTTP 请求,获取网页内容。然后,可以使用 BeautifulSoup 库来解析网页内容,提取需要的数据。 最后,您可以使用 Python 的 Pandas 库将数据保存到本地的 Excel 或 CSV 文件中。以下是一个示例代码: ```python import requests from bs4 import BeautifulSoup import pandas as pd # 发送 HTTP 请求获取网页内容 url = 'https://bj.lianjia.com/ershoufang/' headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'} response = requests.get(url, headers=headers) soup = BeautifulSoup(response.content, 'html.parser') # 解析网页内容,提取需要的数据 house_list = soup.find_all('div', {'class': 'info'}) data = [] for house in house_list: name = house.find('div', {'class': 'title'}).text.strip() price = house.find('div', {'class': 'price'}).text.strip() area = house.find('div', {'class': 'houseInfo'}).text.strip() data.append([name, price, area]) # 将数据保存到本地文件 df = pd.DataFrame(data, columns=['名称', '价格', '面积']) df.to_excel('house_data.xlsx', index=False) ``` 这是一个简单的示例代码,您可以根据您需要爬取的数据和网站的不同来进行修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值