[爬虫] B站番剧信息爬取

news/2024/7/19 11:08:30 标签: 爬虫, scrapy, python

申明:本文对爬取的数据仅做学习使用,不涉及任何商业活动,侵删

简述

本次爬取目标是:

  1. 番剧的基本信息(名字, 类型, 集数, 连载or完结, 链接等)
  2. 番剧的参数信息(播放量, 点赞, 投币, 追番人数等)
  3. 时间信息(开播时间, 完结时间)

前提条件

  1. 编程语言: Python 3
  2. 爬虫框架: Scrapy 1.6.0
  3. 编译器: Pycharm
  4. 平台: Windows

Scrapy安装参考文档:windows / linux

一丶页面分析

番剧索引页展示的番剧信息属于动态渲染, 因此要通过获取页面响应来得到我们想要的数据, 按F12到Network中找我们需要的响应数据:
在这里插入图片描述在这里插入图片描述
来分析一下Request URL, 先无事其他的参数, 来看我们最需要的一部分: page=1&...&pagesize=20

  • page:表示当前页码
  • pagesize:表示页面展示的番剧数

可以尝试访问Request URL, 来确认可以拿到我们需要的数据:
在这里插入图片描述
这一个请求并不能满足需求, 跟进番剧页链接, 并继续找响应数据:
在这里插入图片描述
在这里插入图片描述
几乎所有的数据都被我们得到了, 但唯独缺一个番剧类型
跟进番剧简介网址:https://www.bilibili.com/bangumi/media/md102392, 这是一个静态页面, 可以直接从响应中获取到我们需要的信息:
在这里插入图片描述
完成可数据源的分析, 接下来开始写代码

二丶创建爬虫

  1. 打开cmd控制台,然后cd+路径,移动到到期望的目录中,使用命令创建项目 scrapy startproject bilibili_spider,bilibili_spider为项目名称,创建完成后会自动生成下列文件:
    • bilibili_spider
      • __init__.py
      • scrapy.cfg #项目部署的配置文件
      • bilibili_spider #项目目录, 包含了项目运行相关的文件
        • __init__.py
        • items.py #项目的目标文件
        • middlewares.py #项目的中间件文件
        • pipelines.py #项目的管道文件
        • settings.py #项目的设置文件
        • spiders #项目的爬虫目录
          • __init__.py
  2. 创建爬虫文件,到bilibili_spider\bilibili_spider\spiders目录下,运行命令:scrapy genspider bilibili bilibili.com,bilibili是爬虫文件的名称,后面是目标网站的域名, 由于本次爬取涉及的站点较多, 这里可以将www省略掉, 以避免出错

items.py

进入items.py文件中设置爬取的目标,基于python之禅简单生于复杂, 我将上述最后两次请求合并到一个, 即从番剧详情页获取评论数和评分

python">import scrapy

class BilibiliSpiderItem(scrapy.Item):
    # 索引页的ajax 可以获得以下信息:
    season_id = scrapy.Field()      # 番剧编号
    media_id = scrapy.Field()       # 媒体编号
    title = scrapy.Field()          # 标题
    index_show = scrapy.Field()     # 集数
    is_finish = scrapy.Field()      # 是否完结
    video_link = scrapy.Field()     # 链接
    cover = scrapy.Field()          # 封面图
    pub_real_time = scrapy.Field()  # 真实发布日期
    renewal_time = scrapy.Field()   # 最近更新日期

    # 番剧信息的ajax请求:
    favorites = scrapy.Field()      # 追番
    coins = scrapy.Field()          # 硬币
    views = scrapy.Field()          # 播放量
    danmakus = scrapy.Field()       # 弹幕

    # 番剧详情页的ajax请求:
    cm_count = scrapy.Field()       # 评论数
    score = scrapy.Field()          # 评分
    media_tags = scrapy.Field()     # 类型标签

爬虫文件

python"># -*- coding: utf-8 -*-
import json
from datetime import datetime
import scrapy
from scrapy.spiders import CrawlSpider
from bilibili_video.items import BilibiliSpiderItem


class BilibiliSpider(CrawlSpider):
    name = 'bilibili'
    allowed_domains = ['bilibili.com']

    # 索引页的ajax
    request_url = 'https://bangumi.bilibili.com/media/web_api/search/result?page={}&season_type=1&pagesize=20'
    page = 1
    start_urls = [request_url.format(page)]

    # 番剧信息的ajax请求
    season_url = 'https://bangumi.bilibili.com/ext/web_api/season_count?season_id={}&season_type=1&ts={}'

    # 番剧详情页的ajax请求
    media_url = 'https://www.bilibili.com/bangumi/media/md{}'

    def parse(self, response):
        # if self.page == 2:  # 限制爬取页数,用于测试爬取状态
        #     return
        list_data = json.loads(response.text).get('result').get('data')
        if list_data is None:  # 如果响应中没有数据,则结束执行
            return

        for data in list_data:
            ts = datetime.timestamp(datetime.now())
            yield scrapy.Request(url=self.season_url.format(data.get('season_id'), ts),
                                 callback=self.parse_details,
                                 meta=data)
        self.page += 1  # 生成下一页的请求
        yield scrapy.Request(url=self.request_url.format(self.page),
                             callback=self.parse)

    def parse_details(self, response):
        item = BilibiliSpiderItem()

        meta_data = response.meta
        item['season_id'] = meta_data.get('season_id')
        item['media_id'] = meta_data.get('media_id')
        item['title'] = meta_data.get('title')
        item['index_show'] = meta_data.get('index_show')
        item['is_finish'] = meta_data.get('is_finish')
        item['video_link'] = meta_data.get('link')
        item['cover'] = meta_data.get('cover')
        item['pub_real_time'] = meta_data.get('order').get('pub_real_time')
        item['renewal_time'] = meta_data.get('order').get('renewal_time')

        resp_data = json.loads(response.text).get('result')
        item['favorites'] = resp_data.get('favorites')
        item['coins'] = resp_data.get('coins')
        item['views'] = resp_data.get('views')
        item['danmakus'] = resp_data.get('danmakus')
        yield scrapy.Request(url=self.media_url.format(item['media_id']),
                             callback=self.parse_media,
                             meta=item)

    def parse_media(self, response):
        item = response.meta

        resp = response.xpath('//div[@class="media-info-r"]')
        item['media_tags'] = resp.xpath('//span[@class="media-tags"]/span/text()').extract()
        item['score'] = resp.xpath('//div[@class="media-info-score-content"]/text()').extract()[0]
        item['cm_count'] = resp.xpath('//div[@class="media-info-review-times"]/text()').extract()[0]
        yield item

项目源码链接:https://github.com/zhanghao19/bilibili_spider


http://www.niftyadmin.cn/n/1487963.html

相关文章

[django项目] 用户注册功能 之 用户模型与图片验证码

用户注册功能 之前我们完成了模板的抽取和配置, 前端的目标基本完成, 接下来开始对功能的设计与编写 由浅入深, 先从最基础的用户注册功能来设计 I. 用户模型设计 django的强大之处在于开发效率高,内置了权限模块之类的很多常用功能。在开始一个新的django项目时…

[django项目] 用户注册功能 之 用户名与手机号校验

前言 书接上文, 完成了图片验证码之后, 接下来就是对用户名密码和手机号的校验 相比较而言密码的校验围绕前端代码, 不涉及后台校验, 因此本文密码校验篇幅较少,为的是着重讲解的是用户名和手机号的校验. V. 用户名校验 判断用户名是否被注册, 提示验证信息到页面 1>接口…

[django项目] 用户注册功能 之 发送短信验证码

VIII. 获取短信验证码功能 短信验证码功能相比较用户名和手机号验证来说比较难, 我们来具体的分析一下流程 1>业务流程分析 校验手机号码, 前端校验完后端也要校验, 目的是进一步防止爬虫校验图片验证码设置发送延迟, 检查是否在60s内发送记录生成短信验证码发送短信保存…

[django项目] 用户注册功能 之 注册用户到数据库

VIIII. 注册功能 谋定而后动, 先做分析在写代码 1>业务流程分析 对参数进行校验 判断用户名是否为空,是否已注册判断密码是否为空, 是否一致,格式是否正确判断手机号码是否为空,格式是否正确判断短信验证码是否为空,格式是否…

[django项目] 实现用户登录登出功能

用户登录登出功能 I. 功能需求分析 1>功能分析 1.1>流程图 1.2>功能接口 登录页面登录功能退出功能 II. 登陆页面 1>接口设计 1.1>接口说明 类目说明请求方法GETurl定义/users/login/参数格式无参数 1.2>返回结果 登陆页面 2.后端代码 user/views.…

[django项目] 用户注册登录模块复盘+总结

用户注册登录模块复盘总结 前言 之前我们分别完成了注册模块与登录模块, 距离整个博客网站的搭建又近了一步 接下来对这两个模块做一下总结, 一是回顾之前的知识点, 二是整理自己的代码思路 小编自己首先想到两个问题:为什么不对每个模块做总结? 为什么不在项目的最后总结…

[django项目] 新闻首页功能 之 文章标签导航与新闻列表

新闻主页 I. 功能需求分析 首先我们来看一下首页长什么样(使用的是潭州课堂的模板): 1>功能 剥去顶部,底部和侧边的公共区域不提, 首页上主要的功能有以下五种: 轮播图推荐文章列表文章标签导航文章列表分页功能 II. 模型设计 根据功能分析,我们需要如下…

[django项目] 新闻首页功能 之 展示点击量最高的文章

V. 推荐新闻 在首页展示3篇点击量最高的文章 1>接口设计 接口说明: 类目说明请求方法GETurl定义/参数格式无参数 2.返回内容 返回新闻页面,直接在模板渲染 2>后端代码 2.1>视图代码 # 修改news/views.py中的index视图 def index(reque…