current position:Home>[Python crawler] 10. Scrapy framework

[Python crawler] 10. Scrapy framework

2022-11-08 09:31:59Deng Dashuai


往期内容提要:


一、Scrapy介绍

Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,我们只需要实现少量的代码,就能够快速的抓取.
在这里插入图片描述
这是因为 Scrapy 使用了 Twisted['twɪstɪd]异步网络框架,可以加快我们的下载速度.
在这里插入图片描述

  • 异步:调用在发出之后,这个调用就直接返回,不管有无结果
  • 非阻塞:关注的是程序在等待调用结果(消息,返回值)时的状态,指在不能立刻得到结果之前,该调用不会阻塞当前线程.

在这里插入图片描述
在这里插入图片描述


二、Scrapy的安装介绍

Scrapy框架官方网址:http://doc.scrapy.org/en/latest

Scrapy中文维护站点:http://scrapy-chs.readthedocs.io/zh_CN/latest/index.html

(1) Windows 安装方式

  • Python 2 / 3
  • 升级pip版本:pip install --upgrade pip
  • 通过pip 安装 Scrapy 框架pip install Scrapy

(2) Ubuntu 需要9.10或以上版本安装方式

  • Python 2 / 3
  • 安装非Python的依赖 sudo apt-get install python-dev python-pip libxml2-dev libxslt1-dev zlib1g-dev libffi-dev libssl-dev
  • 通过pip 安装 Scrapy 框架 sudo pip install scrapy

安装后,只要在命令终端输入 scrapy,提示类似以下结果,代表已经安装成功

在这里插入图片描述

具体Scrapy安装流程参考:http://doc.scrapy.org/en/latest/intro/install.html#intro-install-platform-notes 里面有各个平台的安装方法


三、操作案例

学习目标:
  • 创建一个Scrapy项目
  • 定义提取的结构化数据(Item)
  • 编写爬取网站的 Spider 并提取出结构化数据(Item)
  • 编写 Item Pipelines 来存储提取到的Item(即结构化数据)

(1) 新建项目(scrapy startproject)

  • 在开始爬取之前,必须创建一个新的Scrapy项目.进入自定义的项目目录中,运行下列命令:
scrapy startproject mySpider
  • 其中, mySpider 为项目名称,可以看到将会创建一个 mySpider 文件夹,目录结构大致如下:
.
└── mySpider
    ├── mySpide
    │       ├── __init__.py
    │       ├── items.py
    │       ├── pipelines.py
    │       ├── settings.py
    │       └── spiders
    │           └── __init__.py
    └── scrapy.cfg

下面来简单介绍一下各个主要文件的作用:

  • scrapy.cfg :项目的配置文件
  • mySpider/ :项目的Python模块,将会从这里引用代码
    1.mySpider/items.py :项目的目标文件
    2.mySpider/pipelines.py :项目的管道文件
    3.mySpider/settings.py :项目的设置文件
    4.mySpider/spiders/ :存储爬虫代码目录

在这里插入图片描述

(2) 明确目标(mySpider/items.py)

我们打算抓取:http://www.itcast.cn/channel/teacher.shtml 网站里的所有讲师的姓名、职称和个人信息.

  1. 打开mySpider目录下的items.py

  2. Item 定义结构化数据字段,用来保存爬取到的数据,有点像Python中的dict,但是提供了一些额外的保护减少错误.

  3. 可以通过创建一个 scrapy.Item 类, 并且定义类型为 scrapy.Field的类属性来定义一个Item.

  4. 接下来,创建一个ItcastItem 类,和构建item模型(model).

import scrapy

class ItcastItem(scrapy.Item):
    name = scrapy.Field()
    level = scrapy.Field()
    info = scrapy.Field()

(3) 制作爬虫

The crawler function is divided into three steps:

  1. 爬数据
    scrapy genspider itcast "itcast.cn”
  2. 提取数据
    完善spider,使用xpath等方法
  3. 保存数据
    pipeline中保存数据
1. 爬数据
  • A . 在当前目录下输入命令,将在mySpider/spider目录下创建一个名为itcast的爬虫,并指定爬取域的范围:
scrapy genspider itcast "itcast.cn"

在这里插入图片描述

  • B. 打开 mySpider/spider目录里的 itcast.py,默认增加了下列代码:
import scrapy

class ItcastSpider(scrapy.Spider):
    name = "itcast"
    allowed_domains = ["itcast.cn"]
    start_urls = (
        'http://www.itcast.cn/',
    )

    def parse(self, response):
        pass
其实也可以由我们自行创建itcast.py并编写上面的代码,只不过使用命令可以免去编写固定代码的麻烦:

要建立一个Spider, 你必须用scrapy.Spider类创建一个子类,并确定了三个强制的属性 和 一个方法.

  • name = "" :这个爬虫的识别名称,必须是唯一的,在不同的爬虫必须定义不同的名字.The crawler starts to use spider crawl [名字] .

  • allow_domains = [] 是搜索的域名范围,也就是爬虫的约束区域,规定爬虫只爬取这个域名下的网页,不存在的URL会被忽略.

  • start_urls = () :爬取的URL元祖/列表.爬虫从这里开始抓取数据,所以,第一次下载的数据将会从这些urls开始.其他子URL将会从这些起始URL中继承性生成.

  • parse(self, response) :解析的方法,每个初始URL完成下载后将被调用,调用的时候传入从每一个URL传回的Response对象来作为唯一参数,主要作用如下:

    1. 负责解析返回的网页数据(response.body),提取结构化数据(生成item)
    2. 生成需要下一页的URL请求.
# 将start_urls的值修改为需要爬取的第一个url
start_urls = ("http://www.itcast.cn/channel/teacher.shtml",)

# 修改parse()方法
def parse(self, response):
    with open("teacher.html", "w") as f:
        f.write(response.text)

然后运行一下看看,在mySpider目录下执行:

scrapy crawl itcast

是的,就是 itcast,看上面代码,它是 ItcastSpider 类的 name 属性,也就是使用 scrapy genspider命令的爬虫名.

一个Scrapy爬虫项目里,可以存在多个爬虫.各个爬虫在执行时,就是按照 name 属性来区分.

运行之后,如果打印的日志出现 [scrapy] INFO: Spider closed (finished),代表执行完成. 之后当前文件夹中就出现了一个 teacher.html 文件,里面就是我们刚刚要爬取的网页的全部源代码信息.

2. 取数据
  • 爬取整个网页完毕,The next step is the retrieval process,首先观察页面源码:

在这里插入图片描述

<div class="li_txt">
    <h3>  xxx  </h3>
    <h4> xxxxx </h4>
    <p> xxxxxxxx </p>
是不是一目了然?直接上XPath开始提取数据吧.
  • 我们之前在mySpider/items.py 里定义了一个ItcastItem类. 这里引入进来
from mySpider.items import ItcastItem
  • 然后将我们得到的数据封装到一个 ItcastItem 对象中,可以保存每个老师的属性,并使用管道,将spider的数据传到pipeline:
from mySpider.items import ItcastItem

def parse(self, response):
    #open("teacher.html","wb").write(response.body).close()
    # 存放老师信息的集合
    items = []

    for each in response.xpath("//div[@class='li_txt']"):
        # 将我们得到的数据封装到一个 `ItcastItem` 对象
        item = ItcastItem()
        #extract()The method returns a string
        name = each.xpath("h3/text()").extract_first()
        title = each.xpath("h4/text()").extract_first()
        info = each.xpath("p/text()").extract_first()
        
        #items.append(item)

        #将获取的数据交给pipelines
        yield item

    # 返回数据,不经过pipeline
    #return items

为什么要使用yield?让整个函数变成一个生成器,变成generator(生成器)The advantage is that each time it is traversed, it is read into memory one by one,It will not cause the memory usage to increase instantaneously.(python3中的range和python2中的xrange同理)

3. 保存数据
A. 如不使用pipeline,scrapy保存信息的最简单的方法主要有四种,-o 输出指定格式的文件,命令如下:
# json格式,默认为Unicode编码
scrapy crawl itcast -o teachers.json

# json lines格式,默认为Unicode编码
scrapy crawl itcast -o teachers.jsonl

# csv 逗号表达式,可用Excel打开
scrapy crawl itcast -o teachers.csv

# xml格式
scrapy crawl itcast -o teachers.xml
    B. 如使用pipeline,要将所有(从所有'spider'中)爬取到的item,存储到一个独立地items.json 文件,每行包含一个序列化为'JSON'格式的'item':

    (1)打开 pipelines.py 文件,写入下面代码:

    # pipelines.py
    
    import json
    
    class ItcastJsonPipeline(object):
    
        def __init__(self):
            self.file = open('teacher.json', 'wb')
    
        def process_item(self, item, spider):
            content = json.dumps(dict(item), ensure_ascii=False) + "\n"
            self.file.write(content)
            return item
    
        def close_spider(self, spider):
            self.file.close()
    

    (2)启用一个Item Pipeline组件:

    为了启用Item Pipeline组件,必须将它的类添加到 settings.py文件ITEM_PIPELINES 配置,就像下面这个例子:

    # Configure item pipelines
    # See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html
    ITEM_PIPELINES = {
        
        #'mySpider.pipelines.SomePipeline': 300,
        "mySpider.pipelines.ItcastJsonPipeline":300
    }
    

    分配给每个类的整型值,确定了他们运行的顺序,item按数字从低到高的顺序,通过pipeline,通常将这些数字定义在0-1000范围内(0-1000随意设置,数值越低,组件的优先级越高)


    转眼间 [Python爬虫] The topic has been written to chapter ten,More or less has begun to understandPythonThe basic principles and application methods of reptiles,From a staged learning perspective,This concludes the content of this topic,The next study is a more in-depth framework study.Such as here is just simple right Scrapy A brief overview of the framework.如果你对 Scrapy 框架感兴趣,Next will be a new beginning,加油!


    【Python爬虫】Scrapy 后续学习路线

    • [Python爬虫] Scrapy 框架之Scrapy Shell
    • [Python爬虫] Scrapy 框架之Item Pipeline
    • [Python爬虫] Scrapy 框架之Spider
    • [Python爬虫] Scrapy 框架之CrawlSpiders
    • [Python爬虫] Scrapy 框架之Request
    • [Python爬虫] Scrapy 框架之Downloader Middlewares
    • [Python爬虫] Scrapy 框架之Settings
    • [Python爬虫] scrapy-redis

    如果您有任何疑问或者好的建议,期待你的留言与评论!

    copyright notice
    author[Deng Dashuai],Please bring the original link to reprint, thank you.
    https://en.pythonmana.com/2022/312/202211080910333437.html

    Random recommended