Scrapy入门(二)

Scrapy组件详解

Items

爬取的主要目标就是从非结构性的数据源提取结构性数据。Scrapy提供 Item 类来满足这样的需求。
Item 对象是种简单的容器,保存了爬取到得数据。 其提供了 类似于词典(dictionary-like) 的API以及用于声明可用字段的简单语法。

使用Items类仅仅需要继承scrapy的Items类即可
eg

import scrapy
class Product(scrapy.Item):
    name = scrapy.Field()
    price = scrapy.Field()
Field

Field 对象对接受的值没有任何限制。Field 仅仅是内置的 dict 类的一个别名,并没有提供额外的方法或者属性。换句话说, Field 对象完完全全就是Python字典(dict)。被用来基于类属性(class attribute)的方法来支持 item声明语法

Item Pipeline

当Item在Spider中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理。
每个item pipeline组件(有时称之为“Item Pipeline”)是实现了简单方法的Python类。他们接收到Item并通过它执行一些行为,同时也决定此Item是否继续通过pipeline,或是被丢弃而不再进行处理。
以下是item pipeline的一些典型应用:

  • 清理HTML数据
  • 验证爬取的数据(检查item包含某些字段)
  • 查重(并丢弃)
  • 将爬取结果保存到数据库中
    简单的说,Spider用来提取数据,而Pipeline用来处理数据。使用Pipeline将爬取的数据存入数据库的例子会在后面的博客中介绍。

Scrapy框架内部提供了两个Item Pipeline,专门用于下载文件和图片

  • FilesPipeline
  • ImagePipeline
    其中ImagePipeline是FilesPipeline的子类。
    可以在settings中设定FILES_STORE用来指定文件下载目录
    ImagePipeline在FilesPipeline上添加了一些特有功能,在settings里设置IMAGES_THUMBS生成图片缩略图。
    eg
IMAGES_THUMBS={
	'small':(50,50),
	'big':(270,270),
}

还可以过滤尺寸过小的图片,在settings中配置IMAGES_MIN_WIDTHIMAGES_MIN_HEIGHT即可

Settings

Scrapy设定(settings)提供了定制Scrapy组件的方法。您可以控制包括核心(core),插件(extension),pipeline及spider组件。
设定为代码提供了提取以key-value映射的配置值的的全局命名空间(namespace)。 设定可以通过下面介绍的多种机制进行设置。

例如在上面写好了Pipeline,需要在Settings里进行配置,Pipeline才能生效。

ITEM_PIPELINES = {
    'myproject.pipelines.PricePipeline': 300,
    'myproject.pipelines.JsonWriterPipeline': 800,
}

分配给每个类的整型值,确定了他们运行的顺序,item按数字从低到高的顺序,通过pipeline,通常将这些数字定义在0-1000范围内。

更多的设定方式可以在官方文档中查阅。这里列举一些常用的:

  • DEPTH_LIMIT 爬取网站最大允许的深度(depth)值。如果为0,则没有限制。
  • ITEM_PIPELINES 保存项目中启用的pipeline及其顺序的字典。该字典默认为空.
  • RANDOMIZE_DOWNLOAD_DELAY 如果启用,当从相同的网站获取数据时,Scrapy将会等待一个随机的值 (0.5到1.5之间的一个随机值 * DOWNLOAD_DELAY)。该随机值降低了crawler被检测到(接着被block)的机会。某些网站会分析请求, 查找请求之间时间的相似性。
  • ROBOTSTXT_OBEY 如果启用,Scrapy将会尊重 robots.txt策略。
  • USER_AGENT 用户代理

爬取Sklearn文档中所有例子

所爬取文件的起始页https://scikit-learn.org/stable/auto_examples/

创建项目

scrapy startproject sklearnExample

生成模板

cd sklearnExamplescrapy genspider example scikit-learn.org

编写Items类
import scrapy
class SklearnexampleItem(scrapy.Item):
    file_urls = scrapy.Field()
    files = scrapy.Field()
    pass
设置管道

文件以它们URL的 SHA1 hash 作为文件名。为了方便识别,重写文件命名规则

from scrapy.pipelines.files import FilesPipeline
from urllib.parse import urlparse
from os.path import basename, dirname, join
class MyFilesPipeline(FilesPipeline):
    def file_path(self, request, response=None, info=None):
        path = urlparse(request.url).path
        return join(basename(dirname(path)), basename(path))
配置setting
#开启管道
ITEM_PIPELINES = {
    'sklearnExample.pipelines.MyFilesPipeline': 1,
   # 'sklearnExample.pipelines.SklearnexamplePipeline': 300,
}
#设置下载文件位置
FILES_STORE = 'examples_src'
编写爬虫Spider

自己解析html,使用相应的css()方法和xpath()方法获取链接

import scrapy
from scrapy.linkextractors import LinkExtractor
from ..items import SklearnexampleItem

class ExampleSpider(scrapy.Spider):
    name = 'example'
    allowed_domains = ['scikit-learn.org']
    start_urls = ['https://scikit-learn.org/stable/auto_examples/']

    def parse(self, response):
        le = LinkExtractor(restrict_css='div.figure span.caption-text')
        print(len(le.extract_links(response)))
        for link in le.extract_links(response):
            yield scrapy.Request(link.url, callback=self.parse_example)
        pass

    def parse_example(self, response):
        href = response.css('a.reference.download::attr(href)').extract_first()
        url = response.urljoin(href)
        example = SklearnexampleItem()
        example['file_urls'] = [url]
        return example
运行爬虫,查看结果

scrapy crawl example -o example.json 所有文件都被爬下来了,并且爬取的日志也被记录在example.json中。

scrapy 多个item怎么区分 scrapy中的item_ci

爬取360图片

http://image.so.com/z?ch=art每次下拉页面就会发送jquery请求新的图片,使用chrome分析

scrapy 多个item怎么区分 scrapy中的item_数据_02

##### 创建项目

scrapy startproject soImage

生成模板

cd soImagescrapy genspider image image.so.com

配置setting
#开启管道
ITEM_PIPELINES = {
   # 'soImage.pipelines.SoimagePipeline': 300,
    'scrapy.pipelines.images.ImagesPipeline' : 1,
}
#设置下载文件位置
IMAGES_STORE = 'downloadImages'

另外360的网站robots协议是禁止爬虫的,如果不修改scrapy里的设置就无法访问

scrapy 多个item怎么区分 scrapy中的item_ide_03

所以更改setting.py内的Obey robots.txt rules

ROBOTSTXT_OBEY = False

编写爬虫Spider
import scrapy
from scrapy import Request
import json

class ImageSpider(scrapy.Spider):
    name = 'image'
    BASE_URL = 'http://image.so.com/zj?ch=art&sn=%s&listtype=new&temp=1'
    start_index = 0
    MAX_DOWNLOAD_NUM = 1000 #防止下载过多,磁盘使用过大
    start_urls = [BASE_URL % 0]
    def parse(self, response):
        infos = json.loads(response.body.decode('utf-8'))
        print(infos)
        yield {'image_urls' : [info['qhimg_url'] for info in infos['list']]}
        self.start_index += infos['count']
        if infos['count'] > 0 and self.start_index < self.MAX_DOWNLOAD_NUM:
            yield Request(self.BASE_URL % self.start_index)
        pass
运行爬虫,查看结果

scrapy 多个item怎么区分 scrapy中的item_ci_04

所有图片就下载下来了

上一篇:Scrapy入门(一)