当前位置:   article > 正文

[爬虫] B站番剧信息爬取_抓取b站追番数据

抓取b站追番数据

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

简述

本次爬取目标是:

  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之禅简单生于复杂, 我将上述最后两次请求合并到一个, 即从番剧详情页获取评论数和评分

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()     # 类型标签
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
爬虫文件
# -*- 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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

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

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

闽ICP备14008679号