当前位置:   article > 正文

使用Python爬取B站UP主所有视频信息_python爬取b站up主信息

python爬取b站up主信息

目录

一、背景

二、爬虫的实现思路

1、直接requests爬取

2、综合思路

二、代码实现

1、初始化Selenium WebDriver:

2、访问用户视频列表页面

3、翻页处理

4、获取视频详细信息

5、保存数据

6、定义一个运行函数串联所有方法功能

三、实际运行效果

1、selenium爬取视频BV号

2、BV号的json文件

3、execl文件信息


一、背景

之前B站有刷到一个视频,关于某UP主的视频播放数统计,这视频的UP主是个狠人,一个个视频统计,最后算所有视频的播放数,可以是可以,就是有点废人,突然有了想用爬虫的思路了.

首先我们知道B站的每一个视频是BV号,视频的URL是由B站域名加唯一BV号如:

https://www.bilibili.com/video/BV1Qm411S7BP/5分钟了解 蓝色监狱【『剧场版 蓝色监狱 -EPIOSODE 凪-』2024年4月19日公開】_哔哩哔哩_bilibili

那这样爬取的大致思路就是获取所有BV号,再用requests,去爬取视频,获取视频信息

二、爬虫的实现思路

1、直接requests爬取

发现行不通,这里直接在up主页面访问得不到每一个视频的BV号

看样子这个JS脚本是来用于检测用户的信息,并根据这些条件可能会重定向不同的页面。此外,还有一些用于页面性能监控、日志上报和webp图片格式支持检测的脚本。

本菜鸟技术有限,打不过就绕过,直接上selenium来获取所有视频的BV号

2、综合思路

selenium用来获取BV号,爬取到具体的信息保存下来,配合多线程、requests用来爬取具体视频的信息,提高爬取效率,最后用execl保存爬取到的所有信息

二、代码实现

1、初始化Selenium WebDriver:

使用Selenium的Chrome WebDriver来模拟用户在浏览器中的操作,这样可以处理JavaScript渲染的页面

  1. class GetInfo():
  2. def __init__(self, user_id):
  3. self.a_list = [] # 存储每一个视频的url
  4. self.d = webdriver.Chrome() # 初始化Chrome浏览器驱动
  5. self.user_id = user_id
  6. self.base_url = f'https://space.bilibili.com/{user_id}/video'
  7. self.d.get(self.base_url)
  8. #这篇文章写于2022年,当时B站免登入可以搜索视频,查看视频,但是这段时间再次尝试爬取资源时,加了必须认证登入,尝试过很多次,没有获取token,只能老老实实,登入后再去爬取信息
  9. time.sleep(10)
  10. print("速度扫码登入")

实际效果,是可以直接访问,

但是会弹出登入验证,甚至因为未登入无法获取视频列表,接口返回无权限,遇到这种情况,只能登入,尝试过selenium带cookie,但是没用,甚至登入后copy as curl再postman导入请求,都返回无权限,说明搜索接口再请求服务器时候,没有带上cookie

2、访问用户视频列表页面

这里使用XPath定位到视频列表的ul元素,然后遍历其中的li元素,提取每个视频的URL。

  1. def get_url(self):
  2. # 从当前页面获取所有视频的URL并保存到本地文件
  3. ul=WebDriverWait(self.d, 10).until(lambda x: x.find_element(By.XPATH, '//*[@id="submit-video-list"]/ul[1]'))
  4. lis = ul.find_elements(By.XPATH, "li")
  5. for li in lis:
  6. self.a_list.append(li.get_attribute("data-aid"))
  7. with open("url.json", "w+", encoding="utf-8") as f:
  8. data = json.dumps(self.a_list, ensure_ascii=False) # 确保中文字符正常保存
  9. f.write(data) # 使用write而不是writelines

3、翻页处理

首先获取总页数,然后通过点击“下一页”按钮来遍历所有页面,并在每个页面上调用get_urls方法来提取视频URL

  1. def next_page(self):
  2. # 遍历所有页面,获取所有视频的URL)
  3. total = WebDriverWait(self.d, 10).until(lambda x: x.find_element(By.XPATH, '//*[@id="submit-video-list"]/ul[3]/span[1]'))
  4. number = re.findall(r"\d+", total.text)
  5. total = int(number[0])
  6. for page in range(1, total):
  7. try:
  8. self.d.find_element(By.LINK_TEXT, '下一页').click()
  9. time.sleep(2) # 等待页面加载
  10. self.get_url() # 修复方法名错误
  11. except Exception as e:
  12. print(f"Failed to click next page: {e}")
  13. return self.a_list

4、获取视频详细信息

使用requests库来获取每个视频页面的HTML内容,然后调用parse_video_page方法来解析并提取视频的详细信息

  1. def get_video(self, urls, start, end):
  2. # 使用requests.Session()来复用TCP连接
  3. with requests.Session() as session:
  4. session.headers.update({
  5. "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"
  6. })
  7. base_url = "http://www.bilibili.com/video/"
  8. # 预编译正则表达式以提高性能
  9. title_pattern = re.compile(r'<title data-vue-meta="true">([^&amp;]+)</title>')
  10. play_count_pattern = re.compile(r'视频播放量 (\d+)')
  11. danmu_count_pattern = re.compile(r'弹幕量 (\d+)')
  12. like_count_pattern = re.compile(r'点赞数 (\d+)')
  13. coin_count_pattern = re.compile(r'投硬币枚数 (\d+)')
  14. favorite_count_pattern = re.compile(r'收藏人数 (\d+)')
  15. share_count_pattern = re.compile(r'转发人数 (\d+)')
  16. for url in urls[int(start):int(end)]:
  17. full_url = base_url + url
  18. try:
  19. response = session.get(full_url)
  20. if response.status_code == 200:
  21. string = response.text
  22. # 使用正则表达式提取视频信息
  23. title_match = title_pattern.search(string)
  24. title = title_match.group(1) if title_match else "未找到匹配的内容"
  25. # 提取视频播放量、弹幕量等信息
  26. play_count = play_count_pattern.search(string).group(1) if play_count_pattern.search(
  27. string) else '0'
  28. danmu_count = danmu_count_pattern.search(string).group(1) if danmu_count_pattern.search(
  29. string) else '0'
  30. like_count = like_count_pattern.search(string).group(1) if like_count_pattern.search(
  31. string) else '0'
  32. coin_count = coin_count_pattern.search(string).group(1) if coin_count_pattern.search(
  33. string) else '0'
  34. favorite_count = favorite_count_pattern.search(string).group(
  35. 1) if favorite_count_pattern.search(string) else '0'
  36. share_count = share_count_pattern.search(string).group(1) if share_count_pattern.search(
  37. string) else '0'
  38. # 将提取的信息添加到self.data_list中
  39. video_info = {
  40. "url":full_url,
  41. "title": title,
  42. "play_count": play_count,
  43. "danmu_count": danmu_count,
  44. "like_count": like_count,
  45. "coin_count": coin_count,
  46. "favorite_count": favorite_count,
  47. "share_count": share_count
  48. }
  49. self.data_list.append(video_info)
  50. else:
  51. print(f"Failed {full_url}: HTTP {response.status_code}")
  52. except Exception as e:
  53. print(f"Failed to get video info for url {full_url}: {e}")

5、保存数据

导入openpyxl库,用于将数据保存到Excel

  1. def save_to_excel(self, filename):
  2. wb = Workbook()
  3. ws = wb.active
  4. ws.append(['url','标题', '播放量', '弹幕数', '点赞数', '投币数', '收藏数', '分享数']) # 添加表头
  5. for video_info in self.data_list:
  6. ws.append([
  7. video_info['url'],
  8. video_info['title'],
  9. video_info['play_count'],
  10. video_info['danmu_count'],
  11. video_info['like_count'],
  12. video_info['coin_count'],
  13. video_info['favorite_count'],
  14. video_info['share_count']
  15. ])
  16. wb.save(filename)

6、定义一个运行函数串联所有方法功能

  1. def run(self):
  2. # 运行整个流程
  3. self.get_url() # 获取当前页面的视频URL
  4. self.next_page() # 遍历所有页面获取视频URL
  5. with open("url.json", "r", encoding="utf-8") as f:
  6. data = json.load(f)
  7. # 使用多线程提高数据获取效率
  8. threads = []
  9. part = int(len(data) / 3)
  10. for i in range(3):
  11. start = i * part
  12. end = (i + 1) * part if i != 2 else len(data)
  13. thread = threading.Thread(target=self.get_video, args=(data, start, end))
  14. threads.append(thread)
  15. thread.start()
  16. for thread in threads:
  17. thread.join() # 等待所有线程完成
  18. # 所有线程完成后,保存数据到Excel
  19. self.save_to_excel('final_video_info1.xlsx')

三、实际运行效果

  1. if __name__ == '__main__':
  2. obj = GetInfo()
  3. obj.run() # 运行整个流程

1、selenium爬取视频BV号

自动翻页至最后一页

2、BV号的json文件

json文件列表长度和视频号一致

3、execl文件信息

有了这些文件,想统计具体的数据,就很轻松

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/315351
推荐阅读
相关标签
  

闽ICP备14008679号