学习目标:

  1. 掌握 scrapy的安装
  2. 应用 创建scrapy的项目
  3. 应用 创建scrapy爬虫
  4. 应用 运行scrapy爬虫
  5. 应用 scrapy定位以及提取数据或属性值的方法
  6. 掌握 response响应对象的常用属性

1 安装scrapy

命令:sudo apt-get install scrapy

或者:pip/pip3 install scrapy

2 scrapy项目开发流程

  1. 创建项目:scrapy startproject mySpider
  2. 生成一个爬虫:scrapy genspider itcast itcast.cn
  3. 提取数据:根据网站结构在spider中实现数据采集相关内容
  4. 保存数据:使用pipeline进行数据后续处理和保存

3. 创建项目

通过命令将scrapy项目的的文件生成出来,后续步骤都是在项目文件中进行相关操作,下面以抓取传智师资库来学习scrapy的入门使用:http://www.itcast.cn/channel/teacher.shtml

创建scrapy项目的命令:scrapy startproject <项目名字>

示例:scrapy startproject myspider

生成的目录和文件结果如下:

PS C:\Users\myxc\Documents\code\python\demo_spider> tree /f
卷 Windows 的文件夹 PATH 列表
卷序列号为 68B5-629B
C:.
│  scrapy.cfg
│
└─demo_spider
   │  items.py
   │  middlewares.py
   │  pipelines.py
   │  settings.py
   │  __init__.py
   │
   └─spiders
           __init__.py

4. 创建爬虫

通过命令创建出爬虫文件,爬虫文件为主要的代码作业文件,通常一个网站的爬取动作都会在爬虫文件中进行编写。

命令:scrapy genspider <爬虫名字> <允许爬取的域名>(在项目路径下执行)

爬虫名字: 作为爬虫运行时的参数

允许爬取的域名:为对于爬虫设置的爬取范围,设置之后用于过滤要爬取的url,如果爬取的url与允许的域不通则被过滤掉。

示例:

PS C:\Users\myxc\Documents\code\python\demo_spider> scrapy genspider itcast itcast.cn
Created spider 'itcast' using template 'basic' in module:
  demo_spider.spiders.itcast
PS C:\Users\myxc\Documents\code\python\demo_spider> tree /f
卷 Windows 的文件夹 PATH 列表
卷序列号为 68B5-629B
C:.
│  scrapy.cfg
│  
└─demo_spider
    │  items.py(自己预计需要爬取的内容)
    │  middlewares.py(自定义中间件的地方)
    │  pipelines.py(管道,用于保存数据)
    │  settings.py(设置文件、UA、启动管道)
    │  __init__.py
    │  
    ├─spiders(自己定义的spider文件夹)
    │  │  itcast.py(定义spider的文件)
    │  │  __init__.py
    │  │
    │  └─__pycache__
    │          __init__.cpython-37.pyc
    │
    └─__pycache__
            settings.cpython-37.pyc
            __init__.cpython-37.pyc

5. 完善爬虫

在上一步生成出来的爬虫文件中编写指定网站的数据采集操作,实现数据提取

5.1 在/myspider/myspider/spiders/itcast.py中修改内容如下:

import scrapy


class ItcastSpider(scrapy.Spider):
    # 定义爬虫名称
    name = 'itcast'
    # 定义爬虫解析域
    allowed_domains = ['itcast.cn']
    # 定义爬虫起始url
    start_urls = ['http://www.itcast.cn/channel/teacher.shtml#ajavaee']

    def parse(self, response):
        # 定义页面解析的操作

        # with open("itcast.html", "wb") as f:
        #     f.write(response.body)

        teacher_list = response.xpath("//div[contains(@class, 'tea_txt')]//li")
        # print(len(teacher_list))

        for teacher in teacher_list:
            temp_dict = {}

            # temp_dict['name'] = teacher.xpath("//h3/text()") # 注意加点和不加点的区别!!!
            temp_dict['name'] = teacher.xpath(".//h3/text()").extract_first()
            temp_dict['position'] = teacher.xpath(".//h4/text()")[0].extract()
            temp_dict['info'] = teacher.xpath(".//p/text()")[0].extract().replace('\r\n', '')
            # temp_dict['position'] = teacher.xpath("//h2/span/text()")
            # temp_dict['name'] = teacher.xpath("//p[1]")

            print(temp_dict)
注意:
  • scrapy.Spider爬虫类中必须有名为parse的解析
  • 如果网站结构层次比较复杂,也可以自定义其他解析函数
  • 在解析函数中提取的url地址如果要发送请求,则必须属于allowed_domains范围内,但是start_urls中的url地址不受这个限制,我们会在后续的课程中学习如何在解析函数中构造发送请求
  • 启动爬虫的时候注意启动的位置,是在项目路径下启动
  • parse()函数中使用yield返回数据,注意:解析函数中的yield能够传递的对象只能是:BaseItem, Request, dict, None

5.2 定位元素以及提取数据、属性值的方法

解析并获取scrapy爬虫中的数据: 利用xpath规则字符串进行定位和提取

  1. response.xpath方法的返回结果是一个类似list的类型,其中包含的是selector对象,操作和列表一样,但是有一些额外的方法
  2. 额外方法extract():返回一个包含有字符串的列表
  3. 额外方法extract_first():返回列表中的第一个字符串,列表为空没有返回None
  4. 在提取的元素内再次进行提取时,要注意://h3/text()改方法会提取页面内所有元素,并不会从当前元素下提取,正确的方法是:.//h3/text()

两种提取方法的区别:当xpath获取的元素只有一个时,使用extract_first()可以直接提取列表的第一个元素,不需要再加上索引[0],同时,使用extract_first()时,如果xpath未获取元素,会返回一个None,并不会报错;使用extract()提取时,必须要在数组后加上索引值,同时,若xpath提取对象为空(即列表长度为0),那么将报错,程序终止运行。

5.3 response响应对象的常用属性

  • response.url:当前响应的url地址
  • response.request.url:当前响应对应的请求的url地址
  • response.headers:响应头
  • response.requests.headers:当前响应的请求头
  • response.body:响应体,也就是html代码,byte类型
  • response.status:响应状态码

6 保存数据

利用管道pipeline来处理(保存)数据

6.1 在pipelines.py文件中定义对数据的操作

  1. 定义一个管道类
  2. 重写管道类的process_item方法
  3. process_item方法处理完item之后必须返回给引擎
# 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


# useful for handling different item types with a single interface
from itemadapter import ItemAdapter

import json  # 导入json处理模块


class DemoSpiderPipeline:

    def __init__(self):
        self.file = open('itcast.json', 'w', encoding='utf-8') # 设置打开格式,防止保存后乱码

    def process_item(self, item, spider):
        json_data = json.dumps(item, ensure_ascii=False)+',\n' # json格式化

        self.file.write(json_data) # 写入json数据

        return item  # 数据处理完毕将数据返回给爬虫引擎

    def __del__(self):
        self.file.close()

6.2 在settings.py配置启用管道

ITEM_PIPELINES = {
    'myspider.pipelines.ItcastPipeline': 400
}

配置项中键为使用的管道类,管道类使用.进行分割,第一个为项目目录,第二个为文件,第三个为定义的管道类。配置项中值为管道的使用顺序,设置的数值约小越优先执行,该值一般设置为1000以内。

未在设置里激活Pipeline之前,可以看到爬虫运行时打印的日志中开启的管道列表为空:

(开启管道前)
2020-08-27 16:02:08 [scrapy.middleware] INFO: Enabled item pipelines:
[]
(开启管道后)
2020-08-27 16:08:28 [scrapy.middleware] INFO: Enabled item pipelines:
['demo_spider.pipelines.DemoSpiderPipeline']

7. 运行scrapy

命令:在项目目录下执行scrapy crawl <爬虫名字>

示例:scrapy crawl itcast

PS C:\Users\myxc\Documents\code\python\demo_spider> scrapy crawl itcast --nolog (不打印运行日志)

小结

  1. scrapy的安装:pip install scrapy
  2. 创建scrapy的项目: scrapy startproject myspider
  3. 创建scrapy爬虫:在项目目录下执行 scrapy genspider itcast itcast.cn
  4. 运行scrapy爬虫:在项目目录下执行 scrapy crawl itcast
  5. 解析并获取scrapy爬虫中的数据:

    1. response.xpath方法的返回结果是一个类似list的类型,其中包含的是selector对象,操作和列表一样,但是有一些额外的方法
    2. extract() 返回一个包含有字符串的列表
    3. extract_first() 返回列表中的第一个字符串,列表为空没有返回None
  6. scrapy管道的基本使用:

    1. 完善pipelines.py中的process_item函数
    2. 在settings.py中设置开启pipeline
  7. response响应对象的常用属性

    1. response.url:当前响应的url地址
    2. response.request.url:当前响应对应的请求的url地址
    3. response.headers:响应头
    4. response.requests.headers:当前响应的请求头
    5. response.body:响应体,也就是html代码,byte类型
    6. response.status:响应状态码