关于b站爬虫的尝试(二)

前几天学习了scrapy的框架结构和基本的使用方法,部分内容转载自:http://blog.csdn.net/qq_30242609/article/details/52810840

scrapy由编写蜘蛛的spiders文件夹和其他框架自带的几个python文件组成

其中

items.py

双击打开这个文件,看一下都初始化了什么东西

# -*- coding: urf-8 -*-
# Define here the models for your scrapyed items
#
# See documentation in
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy

class HeartsongItem(scrapy.Item):
    # define the fields for your item here like:
    # 
    # name = scrapy.Filed()
    pass
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

通过里面的注释可见,这个文件的作用是定义我们要爬取信息的标准格式,打个比方说,如果我们要爬取一批人的个人信息,包括姓名,性别,生日,那么我们可以这样来书写这个文件

import scrapy

class HeartsongItem(scrapy.Item):
   name = scrapy.Filed()
   sex = scrapy.Filed()
   birthday = scrapy.Filed()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

易见本文件只是定义了一个类,至于什么时候实例化它,怎么保存它,请继续了解下面的内容。

settings.py

如其名,这是本项目的配置文件,里面注释着很多常用的配置项,我们通过在其他文件中引入本文件的方式来使用这些配置项。 
当然,我们可以把这些注释都删掉,等需要开启哪个功能的时候再另行编辑。 
我们此处先看看默认打开的配置项吧

BOT_NAME = 'heartsong'
SPIDER_MODULES = ['heartsong.spiders']
NEWSPIDER_MODULE = 'heartsong.spider'
# Obey robots.txt rules
ROBORSTXT_OBEY = True
  • 1
  • 2
  • 3
  • 4
  • 5

因为我们写的是定向爬虫,前面三个按默认即可,我们不去管他。看第四项,注释里说这个配置项的意思是是否遵守robots.txt,那么robots.txt是个什么东西呢? 
通俗来说,robots.txt是遵循Robot协议的一个文件,它保存在网站的服务器中,它的作用是,告诉搜索引擎爬虫,本网站哪些目录下的网页不希望你进行爬取收录。在Scrapy启动后,会在第一时间访问网站的robots.txt文件,然后决定该网站的爬取范围。 
当然,我们并不是在做搜索引擎,而且在某些情况下我们想要获取的内容恰恰是被robots.txt所禁止访问的。所以,我们就将此配置项设置为False,拒绝遵守Robot协议

pipelines.py

双击打开这个文件,看看都初始化了什么东西

# -*- coding: utf-8 -*-

# Define your item pipelines here
# 
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html

class HeartsongPipeline(object):
    def process_item(self, item, spider):
        return item
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

从注释中所能得到的信息微乎其微,只告诉我们要启用此文件的话必须要在settings.py里配置一下ITEM_PIPELINES,好,那我们就老老实实的去settings.py里配置一下吧,不过注意,此处有坑,在1.0.x版本(极客学院教程中使用),配置项用list格式来书写,而在最新的1.1.2版本中,需要用dict格式,否则会报错,无法爬取,配置好后,我们的setting.py如下:

# -*- coding: utf-8 -*-

BOT_NAME = 'heartsong'
SPIDER_MODULES = ['heartsong.spiders']
NEWSPIDER_MODULE = 'heartsong.spider'

ROBORSTXT_OBEY = True

ITEM_PIPELINES = {
    'heartsong.pipelines.HeartsongPipeline': 300,
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

此处的300表示优先级,因为本项目只用到这一个pipeline,所以随意取0-1000中的一个数值即可。 
好,镜头切回pipelines.py,这个文件到底有什么用呢?当然用处很多啦,本教程中介绍的作用只有两个: 
* 对爬取到的数据(Item)进行处理,比如存入数据库 
* 爬虫结束时产生事件,比如发送一封邮件

爬虫

在默认生成的spiders目录下新建heartsong_spider.py,我们的爬虫就写在这里面,因为是介绍,那么此处就写个简单的下载网站的主页,让大家能运行一下,感受一下scrapy。

import scrapy

class HeartsongSpider(scrapy.spiders.Spider):
    name = "heartsong"  # 爬虫的名字,执行时使用
    allowed_domains = ["heartsong.top"]  # 允许爬取的域名,非此域名的网页不会爬取
    start_urls = [
        "http://www.heartsong.top"  # 起始url,此例只爬这一个页面   
    ]

    def parse(self, response):  # 真正的爬虫方法
        html = response.body  # response是获取到的来自网站的返回
        # 以下四行将html存入文件
        filename = "index.html"
        file = open(filename, "w")
        file.write(html)
        file.close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

要说明的是,这个类不是随心所欲来写的,name,allowed_domains,start_urls,都是类似于”重载”的值。也就是说,scrapy内部会检测这些变量的值,变量名不可以起成其它的名字,类似的变量之后还会有介绍。至于parse方法,就是重载的父类的方法,我们爬虫的主体一般就写在这里面。 
好,现在让我们来运行它 
在命令行中进入heartsong目录下,执行命令

scrapy crawl heartsong
  • 1

此处的名字heartsong是与爬虫类中的name保持一致。   

以上是scrapy的基本架构。

由于递归爬取的时候存在超链接指向图片等问题反而增加request工作量,目前主要思考通过首先爬取所有up主信息,再爬取其空间内视频信息的办法。但是具体的爬取方案无法确定。如果要采取不遗漏的方法,又只能从视频方面开始爬取,回到了最初的问题。目前error视频的数量大概占总数量的一半,问题还不是很大,暂时搁置递归爬取的问题。

目前依然采取根据av号枚举的方式访问视频并记录信息。根据测试程序的反馈,scrapy的爬取效率并不比request的方法高多少。。。可能有部分人认为的效率高主要由于scrapy自带的多进程爬取的方法。但是当request也采取多进程爬取时,主要耗时依然在于获取网络源码的过程中。这部分的时间目前没有办法减少。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import scrapy
import re

class bilibili(scrapy.Spider):
name = "bilibili"
# 允许的域名
allowed_domains = ["bilibili.com"]
start_urls = []
for av in xrange(10000):
start_urls.append("http://www.bilibili.com/video/av"+str(av))

def parse(self, response):
page = response.body
temp = re.search(r'<div class="v-title"><h1 title="(.+?)">', page)
if temp:
title = re.search(r'<div class="v-title"><h1 title="(.+?)">', page).group(1)
authorkit = re.search(r'r-info.+?title="(.+?)"', page)
if authorkit:
author = authorkit.group(1)
aid = re.search(r'aid=(d+)', page).group(1)
cid = re.search(r'cid=(d+)', page).group(1)
print cid
print aid
url = 'https://api.bilibili.com/x/web-interface/archive/stat?aid='+str(aid)
return scrapy.http.Request(url=url, callback=self.parse_item_page)

def parse_item_page(self, response):
print response.body
原文地址:https://www.cnblogs.com/silencestorm/p/8513076.html