[Python]爬虫框架scrapy学习,读了这篇文章就可以上手scrapy


最近在研究scrapy框架,在这里简单整理下scrapy使用步骤进行记录,也方便大家阅读。

1. 安装scrapy

pip install scrapy

2. 创建scrapy项目

# projectname为项目名称,可自定义
scrapy startproject projectname

创建项目后会看到以项目名称为名的目录,目录下面的结构如下所示

projectname/
    scrapy.cfg            # 配置文件

    projectname/             # 爬虫模块文件夹
        __init__.py

        items.py          # items定义文件

        middlewares.py    # 中间件middlewares文件

        pipelines.py      # 项目管道pipelines文件

        settings.py       # 设置settings文件

        spiders/          # 爬虫文件夹
            __init__.py

3. scrapy框架工作原理

在编写前首先要了解scrapy的工作原理

3.1 scrapy框架工作流程图

scrapy框架工作流程图

3.2 Scrapy数据流讲解

  1. 爬虫引擎Engine从爬虫Spiders中获得初始请求开始抓取。
  2. 爬虫引擎EngineE开始请求调度程序Scheduler,并准备对下一一次的请求Request进行抓取。
  3. 爬虫调度器Scheduler返回下一个请求Request给爬虫引擎Engine。
  4. 引擎Engine请求发送到下载器Downloader,通过下载中间件Middleware下载网络数据。
  5. 一旦下载器Downloader完成页面下载,将下载结果Response返回给爬虫引擎Engine。
  6. 引擎Engine将下载器Downloader的响应通过中间件Middleware返回给爬虫Spiders进行处理。
  7. 爬虫Spiders处理响应Response,并通过中间件Middleware返回处理后的Items,以及新的请求Request给引擎Engine。
  8. 引擎Engine发送处理后的Items给到项目管道Pipelines进行存储或其他处理,把处理后的Requests给调度器Scheduler,调度器Scheduler计划处理下一个请求抓取。

3.3 各个组件的讲解

  1. 爬虫引擎(ENGINE)
    爬虫引擎负责控制各个组件之间的数据流,当某些操作触发事件后都是通过engine来处理。
  2. 调度器(SCHEDULER)
    调度器接收来子engine的请求并将请求放入队列中,并通过事件返回给engine。
  3. 下载器(DOWNLOADER)
    通过engine请求下载网络数据并将结果响应给engine。
  4. Spider
    Spider发出请求,并处理engine返回给它下载器响应数据,以items和规则内的数据请求(urds)返回给engine。
  5. 管道项目(item pipeline)
    负责处理engine返回spider解析后的数据,并且将数据持久化,例如将数据存入数据库或者文件。
  6. 下载中间件(MIDDLEWARE)
    下载中间件是engine和下载器交互组件,以钩子(插件)的形式存在,可以代替接收请求处理数据的下载以及将结果响应给engine.
  7. spider中间件(MIDDLEWARE)
    spider中间件是engine和spider之间的交互组件,以钩子(插件)的形式存在,可以代替处理responsel以及返回给engineitems及新的请求集。

4. 提取数据

提取数据前要先定位元素,scrapy中可以使用xpath进行定位,也可以使用CSS进行定位,实例如下

response.xpath('//span/text()').get()
response.css('span::text').get()

详细的这里不做记录了,请百度。

5. 爬虫编写步骤

  1. 找到要爬取的网站
  2. 找到要获取的数据,定义items,在items.py中定义要获取的内容,item内容在spiders的parse函数中赋值
  3. 在spiders目录下创建一个Python文件,该文件用来处理爬虫。文件中需要创建一个继承scrapy.Spider的类,类中定义一个爬虫名,并定义需要爬取的网址;在parse函数中解析爬到的数据,并对应到items
  4. 在pipeline中编写数据持久化的方法,如存入数据库或存入文件
  5. 如若需要,可在中间件Middleware.py中编写需要的处理过程

6. 执行爬虫

爬虫写好后当然就是要迫不及待的执行试试了

# projectname为项目名称
scrapy crawl projectname

# 在shell中执行scrapy,URL为要爬取的网址
scrapy shell URL

7. 测试项目案例(附源码)

为了学习这里就使用豆瓣进行测试,实现将图书详细信息页面的信息进行存储,我是用《百年孤独》页面来做测试的,其网址为https://book.douban.com/subject/6082808
我创建的项目名称为booksearch,使用的爬虫名为book,爬取后,会解析出书名、作者、出版社、原作名、译者、出版年、页数、定价、装帧、丛书、ISBN码、评分,并以json的形式存到book.json文件中,读取json文件如下图所示
在这里插入图片描述
下面上代码
项目文件结构

booksearch/
    scrapy.cfg            # 配置文件

    booksearch/             # 爬虫模块文件夹
        __init__.py

        items.py          # items定义文件

        middlewares.py    # 中间件文件

        pipelines.py      # 项目管道文件

        settings.py       # 设置文件,设置headers、执行优先级、robots开关等设置

        spiders/          # 爬虫文件夹
            __init__.py
            book_spider.py	# 爬虫文件,负责爬取图书页面

爬虫文件

# -*- coding: utf-8 -*-
import scrapy
from booksearch.items import BooksearchItem


class BookSpider(scrapy.Spider):
    name = 'book'
    allowed_domains = ['book.douban.com']

    def __init__(self,url=None, *args, **kwargs):
        super(BookSpider, self).__init__(*args, **kwargs)
        self.start_urls = [r'https://book.douban.com/subject/6082808/',]

    def parse(self, response):
        print('开始处理')
        item = BooksearchItem()
        # 书名
        item['title'] = response.xpath("//span[@property='v:itemreviewed']/text()").extract()[0]
        
        # 获取图书信息后解析
        temp_dict = {}
        temp_list = []
        tmp = response.xpath('//div[@id="info"]')
        for i in tmp.xpath('.//text()').extract():
            i=i.replace(' ', '').strip('\n').strip()
            if len(i)>0:
                if '作者' in i:
                    i = '作者:'
                if '译者' in i:
                    i = '译者:'
                if ':' not in i:
                    i = i + ';'
                if i == ':':
                    continue
                temp_list.append(i.replace(' ', '').strip('\n').strip())
        temp_str = ''.join(temp_list)
        temp_list2 = temp_str.split(';')
        for i in temp_list2:
            if len(i)>0:
                temp_dict.update({i.split(':')[0]:i.split(':')[1]})
        if '作者' in temp_dict.keys():
            item['author'] = temp_dict['作者'] # 作者
        if '出版社' in temp_dict.keys():
            item['publisher'] = temp_dict['出版社'] # 出版社
        if '原作名' in temp_dict.keys():
            item['original_title'] = temp_dict['原作名'] # 原作名
        if '译者' in temp_dict.keys():
            item['translator'] = temp_dict['译者'] # 译者
        if '出版年' in temp_dict.keys():
            item['pub_date'] = temp_dict['出版年'] # 出版年
        if '页数' in temp_dict.keys():
            item['pages'] = temp_dict['页数'] # 页数
        if '定价' in temp_dict.keys():
            item['price'] = temp_dict['定价'] # 定价
        if '装帧' in temp_dict.keys():
            item['bingding'] = temp_dict['装帧'] # 装帧
        if '丛书' in temp_dict.keys():
            item['series'] = temp_dict['丛书'] # 丛书
        if 'ISBN' in temp_dict.keys():
            item['isbn'] = temp_dict['ISBN'] # ISBN码
        
        # 获取评分
        item['star'] = response.xpath("//strong/text()").get()
        yield item

itmes文件

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

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy


class BooksearchItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field() # 书名
    author = scrapy.Field() # 作者
    publisher = scrapy.Field() # 出版社
    original_title = scrapy.Field() # 原作名
    translator = scrapy.Field() # 译者
    pub_date = scrapy.Field() # 出版年
    pages = scrapy.Field() # 页数
    price = scrapy.Field() # 定价
    bingding = scrapy.Field() # 装帧
    series = scrapy.Field() # 丛书
    isbn = scrapy.Field() # ISBN码
    star = scrapy.Field() # 评分

项目管道文件

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

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

class BooksearchPipeline(object):
    def process_item(self, item, spider):
        print('开始存储爬取内容')
        line = json.dumps(dict(item)) + "\n"
        print(line)
        with open('book.json', 'w') as f:
            f.write(line)
        return item
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值