鱼C论坛

 找回密码
 立即注册
查看: 1720|回复: 1

[作品展示] b站视频下载 爬虫

[复制链接]
发表于 2021-12-17 15:56:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
单线程版本
  1. #单线程版本
  2. import requests,re,json
  3. from pathlib import Path
  4. from ffmpy3 import FFmpeg
  5. from tqdm import tqdm

  6. headers={"Cookie":"SESSDATA=这里填自己的",
  7.     "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36 Edg/96.0.1054.41",
  8.     "Referer":"https://www.bilibili.com/"}

  9. def get_video_info(video_url:str):
  10.     """[通过正则表达式定位文本 得到视频信息]

  11.     Args:
  12.         video_url (str): [视频链接]

  13.     Returns:
  14.         [type]: [包含视频信息的字典]
  15.     """
  16.     video_html=requests.get(video_url,headers=headers)

  17.     #<span class="cur-page">(1/12)</span>
  18.     pages=re.findall(r'<span class="cur-page">\((.*?)\)</span>', video_html.text)  #分页视频总数

  19.     total_page=1
  20.     if len(pages) !=0:
  21.         cur_page=str(pages[0]).split('/')[0]
  22.         total_page=int(str(pages[0]).split('/')[1])
  23.         print(f'当前为多p视频总页数为{total_page},当前页数为{cur_page}')
  24.     else:
  25.         print('当前为单p视频')

  26.     video_info={}

  27.     for p in range(1,total_page+1):
  28.         video_url=re.sub('p=.*', f'p={p}', video_url)
  29.         video_html=requests.get(video_url,headers=headers)

  30.         video_down_re=re.findall(r'<script>window\.__playinfo__=(.*?)</script>', video_html.text) #下载信息
  31.         video_down_json=json.loads(video_down_re[0])

  32.         video_base_re=re.findall(r'<script>window.__INITIAL_STATE__=(.*?);\(function\(\)', video_html.text) #基本信息
  33.         video_base_json=json.loads(video_base_re[0])

  34.         video_title=video_base_json['videoData']['pages'][p-1]['part']
  35.         video_info[video_title]=dict(video_download_url=video_down_json['data']['dash']['video'][0]['baseUrl'],audio_download_url=video_down_json['data']['dash']['audio'][0]['baseUrl'])

  36.     return video_info

  37. def video_download(video_title:str,video_download_url:str,audio_download_url:str):
  38.     """[下载并合拼视频和音频]

  39.     Args:
  40.         video_title:str 视频标题
  41.         video_download_url (str): [视频下载链接]
  42.         audio_download_url (str): [音频下载链接]
  43.     """
  44.     res=requests.get(url=video_download_url,headers=headers,stream=True)

  45.     chunk_size=1024 #每次下载大小  byte
  46.     content_size=int(res.headers['Content-Length']) # 总大小 byte
  47.    
  48.     # pbar=tqdm(total=content_size,desc=f'{video_title}.mp4',ncols=100,unit='byte',unit_scale=True)  #进度条
  49.     # with open(f'{video_title}.mp4','wb') as stream:
  50.     #     for data in res.iter_content(chunk_size=chunk_size):  #分块读取数据
  51.     #         stream.write(data)
  52.     #         pbar.update(len(data))
  53.     # pbar.close()

  54.     res=requests.get(url=audio_download_url,headers=headers)
  55.     content_size=int(res.headers['Content-Length']) # 总大小 byte

  56.     pbar=tqdm(total=content_size,desc=f'{video_title}.mp3',ncols=100,unit='byte',unit_scale=True)  #进度条
  57.     with open(f'{video_title}.mp3','wb') as stream:
  58.         for data in res.iter_content(chunk_size=chunk_size):  #分块读取数据
  59.             stream.write(data)
  60.             pbar.update(len(data))
  61.     pbar.close()

  62.     # #合并文件
  63.     # ff = FFmpeg(inputs={f'{video_title}.mp4':None,f'{video_title}.mp3':None},outputs={f'{video_title}.mkv':'-codec copy'})
  64.     # ff.run()
  65.     # #删除文件
  66.     # Path(f'{video_title}.mp3').unlink()
  67.     # Path(f'{video_title}.mp4').unlink()
  68.    
  69. if __name__=='__main__':
  70.     url='https://www.bilibili.com/video/BV1f3411B7HK?p=1'
  71.     video_info=get_video_info(video_url=url)

  72.     import time
  73.     start_time=time.time()
  74.     video_titles=video_info.keys()
  75.     for title in video_titles:
  76.         video_download(title,video_info[title]['video_download_url'],video_info[title]['audio_download_url'])
  77.    
  78.     print(f'time={time.time()-start_time}')
  79.    
复制代码


异步协程版本
  1. # 单线程异步协程版本
  2. import asyncio
  3. import re
  4. import aiohttp
  5. import aiofiles
  6. import json
  7. import requests
  8. from tqdm.asyncio import tqdm
  9. from pathlib import path
  10. from ffmpy3 import FFmpeg

  11. headers = {"Cookie": "SESSDATA=这里填自己的",
  12.            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36 Edg/96.0.1054.41",
  13.            "Referer": "https://www.bilibili.com/"}


  14. async def get_video_pages(video_url: str) -> int:
  15.     '''
  16.     得到多p视频 总p数
  17.     :param video_url:当前视频链接
  18.     :return:总p数
  19.     '''
  20.     video_html = requests.get(url=video_url, headers=headers).text
  21.     # <span class="cur-page">(1/12)</span>
  22.     pages = re.findall(r'<span class="cur-page">\((.*?)\)</span>', video_html)  # 分页视频总数

  23.     total_page = 1
  24.     if len(pages) != 0:
  25.         cur_page = str(pages[0]).split('/')[0]
  26.         total_page = int(str(pages[0]).split('/')[1])
  27.         print(f'当前为多p视频总页数为{total_page},当前页数为{cur_page}')
  28.     else:
  29.         print('当前为单p视频')

  30.     return total_page


  31. async def video_download(video_url: str, page: int):
  32.     '''
  33.     下载视频,音频,合并视频使用FFmpeg
  34.     :param video_url:当前链接
  35.     :param page: 当前p数
  36.     :return: 无
  37.     '''
  38.     async with aiohttp.ClientSession() as session:
  39.         async with session.get(url=video_url, headers=headers) as res:
  40.             video_html = await res.text()

  41.             video_down_re = re.findall(r'<script>window\.__playinfo__=(.*?)</script>', video_html)  # 下载信息
  42.             video_down_json = json.loads(video_down_re[0])

  43.             video_base_re = re.findall(r'<script>window.__INITIAL_STATE__=(.*?);\(function\(\)', video_html)  # 基本信息
  44.             video_base_json = json.loads(video_base_re[0])

  45.             video_title = video_base_json['videoData']['pages'][page - 1]['part']  # 标题
  46.             video_download_url = video_down_json['data']['dash']['video'][0]['baseUrl']  # 视频链接
  47.             audio_download_url = video_down_json['data']['dash']['audio'][0]['baseUrl']  # 音频链接

  48.             # async with session.get(url=video_download_url, headers=headers) as res_video:
  49.             #     video_byte=await res_video.read()
  50.             async with session.get(url=audio_download_url, headers=headers) as res_audio:
  51.                 audio_byte = await res_audio.read()
  52.             # async with aiofiles.open(f'{video_title}.mp4','wb') as stream:
  53.             #     await stream.write(video_byte)
  54.             async with aiofiles.open(f'{video_title}.mp3', 'wb') as stream:
  55.                 await stream.write(audio_byte)

  56.             # # 合并文件
  57.             # ff = FFmpeg(inputs={f'{video_title}.mp4': None, f'{video_title}.mp3': None},outputs={f'{video_title}.mkv': '-codec copy'})
  58.             # ff.run()
  59.             # # 删除文件
  60.             # Path(f'{video_title}.mp3').unlink()
  61.             # Path(f'{video_title}.mp4').unlink()


  62. async def main():
  63.     url = 'https://www.bilibili.com/video/BV1f3411B7HK?p=1'
  64.     task_one = asyncio.create_task(get_video_pages(video_url=url))
  65.     toatl_pages = await task_one

  66.     tasks=[]
  67.     for p in range(1, toatl_pages + 1):
  68.         video_url = re.sub('p=.*', f'p={p}', url)
  69.         tasks.append(video_download(video_url,p))

  70.     import time
  71.     start = time.time()
  72.     with tqdm(asyncio.as_completed(tasks),total=len(tasks),unit='byte',unit_scale=True) as pbar:
  73.         for j in pbar:
  74.             await j
  75.     print(f'time={time.time() - start}')

  76. if __name__ == '__main__':
  77.     loop=asyncio.new_event_loop()
  78.     asyncio.set_event_loop(loop)
  79.     loop.run_until_complete(main())
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-12-19 20:41:34 | 显示全部楼层
厉害,可以请楼主帮忙看看这个问题吗爬虫代码有问题请各位大佬指点 [url]https://fishc.com.cn/thread-207084-1-1.html (出处: 鱼C论坛)[/url]
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-30 19:08

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表