n1ming 2024-02-23 15:44 采纳率: 100%
浏览 115
已结题

关于爬b站视频遇到的403问题

最近学习爬虫,想练练手,爬取b站的视频。然后选中了最近看的,

url = ‘https://www.bilibili.com/video/BV1eu4m1P7Pj/?spm_id_from=333.337.search-card.all.click&vd_source=a710d8ce6c660aea6bcb6930aeede828’

一共30P。
这里我先说一下我遇到的问题:视频和音频我是分开爬取的,问题出在爬取的视频上,日志返回的信息是403,并且视频 url 输出的 html文本里写着:

<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>openresty</center>
</body>
</html>
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->

我的处理:
1.我试着将请求头里的信息完善(能抄的我都抄了上去),不管用
2.我将SSL证书关掉,也不管用
3.我又设置了代理,也不行
4.我又试了试HTTP2.0的请求,不行。
5.我搜索了其他博客相关的信息,有的说是服务器磁盘空间不足。

下面是我的代码,请各位赏脸帮帮我吧,我真的搞了好久(我太笨了,实在没办法了)QWQ

import requests
from lxml import etree
import re
import logging


base_url = 'https://www.bilibili.com/video/BV1eu4m1P7Pj/'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0'}
total_page = 30
logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(levelname)s:- %(message)s')


'''爬取网页'''


def scrape_page(url):
    logging.info('开始爬取 %s...',url)
    try:
        response = requests.get(url,headers=headers)
        if response.status_code == 200:
            return response.text
        logging.error('请求失败,响应状态码:%s  url:%s',response.status_code,url)
    except requests.RequestException:
        logging.error('发生其他错误。url: %s',url,exc_info=True)


'''爬取详情页'''


def scrape_index(page):
    url_index = f'{base_url}?p={page}&vd_source=a710d8ce6c660aea6bcb6930aeede828'
    return scrape_page(url_index)


'''解析网页'''


def analysis_page(html):
    result = etree.HTML(html)
    result1 = result.xpath('//script[4]/text()')  # 这里主要是在练习xpath
    url_video_pattern = re.compile('"bandwidth".*?"id":32,"baseUrl":"(.*?)","base_url"',re.S)
    url_music_pattern = re.compile('.*?"id":30280,"baseUrl":"(.*?)","base_url"',re.S)
    url_video = re.search(url_video_pattern,str(result1)).group(1).strip() if re.search(url_video_pattern,str(result1)) else None
    url_music = re.search(url_music_pattern,str(result1)).group(1).strip() if re.search(url_music_pattern,str(result1)) else None
    logging.info('获取的video: %s   music: %s',url_video,url_music)
    return url_video,url_music


'''转换成二进制数据'''


def bytes_data(url):
    logging.info('开始转换成二进制 %s...', url)
    try:
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            return response.content
        logging.error('请求失败,响应状态码:%s  url:%s', response.status_code, url)
    except requests.RequestException:
        logging.error('发生其他错误。url: %s', url, exc_info=True)


'''保存文件'''


def save_video(content):
    logging.info(f'开始保存video{i}中...')
    try:
       path = f'D:\\爬取的b站视频\\video\\video-{i}.mp4'
       with open(path,'wb') as f:
           f.write(content)
           logging.info(f'保存video{i}成功')
    except PermissionError:
        logging.error('没有足够的权限访问或修改文件')
    except TypeError:
        logging.error(f'保存video{i}失败')


def save_music(content):
    logging.info(f'开始保存music{i}中...')
    try:
        path = f'D:\\爬取的b站视频\\music\\music-{i}.mp3'
        with open(path, 'wb') as f:
            f.write(content)
            logging.info(f'保存music{i}成功')
    except PermissionError:
        logging.error('没有足够的权限访问或修改文件')
    except TypeError:
        logging.error(f'保存music{i}失败')


def main():
    global i
    i = 0
    for page in range(1,total_page+1):
        i = i+1
        html = scrape_index(page)
        data_url = analysis_page(html)
        contents_video = bytes_data(data_url[0])
        contents_music = bytes_data(data_url[1])
        save_music(contents_music)
        save_video(contents_video)


if __name__ == '__main__':
    main()

到目前为止,我只是实现了视频和音频的分别爬取和保存。但是令人遗憾的是我只成功的爬取了所有的音频,而视频除了第一个,其他的全失败,全是403. QWQ。

为了看的更清楚,我把我遇到的问题和尝试的思路再描述一下。
视频和音频我是分开爬取的,问题出在爬取的视频上,日志返回的信息是403,并且视频 url 输出的 html文本里写着:

<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>openresty</center>
</body>
</html>
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->

我的处理:
1.我试着将请求头里的信息完善(能抄的我都抄了上去),不管用
2.我将SSL证书关掉,也不管用
3.我又设置了代理,也不行
4.我又试了试HTTP2.0的请求,不行。
5.我搜索了其他博客相关的信息,有的说是服务器磁盘空间不足。

  • 写回答

4条回答 默认 最新

  • 冰履踏青云 2024-02-23 17:00
    关注

    恰好刷到,我来解答一下,b站好像有refer检测,所以你只需要在scrape_page方法里加上headers['Referer'] = url应该就能解决你的问题,即:

    def scrape_page(url):
        logging.info('开始爬取 %s...',url)
        try:
            headers['Referer'] = url
            response = requests.get(url,headers=headers)
            if response.status_code == 200:
                return response.text
            logging.error('请求失败,响应状态码:%s  url:%s',response.status_code,url)
        except requests.RequestException:
            logging.error('发生其他错误。url: %s',url,exc_info=True)
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 3月2日
  • 已采纳回答 2月23日
  • 创建了问题 2月23日