Python爬虫框架Scrapy应用实战解析

内容导读

  1. Scrapy框架简介
  2. 通过Scrapy爬取文本信息
  3. 定制下载器中间件

一、Scrapy框架简介

Scrapy是一个为了爬取网站数据,提取结构化数据而编写的应用程序框架,可以应用在包括数据挖掘、信息处理或存储历史数据等一系列功能的程序中。

该框架也可以应用在获取API(如Amazon Associates Web Services的API)所返回的数据或通用的网络爬虫中。

在使用Scrapy框架之前,需要先了解该框架的构成、常用命令。

使用Scrapy爬取某企业官网新闻动态。

1、了解Scrapy爬虫框架

Scrapy是一个爬虫框架而非功能函数库,简单地说,它是一个半品,可以帮助用户简单快速地部署一个专业的网络爬虫。

Scrapy爬虫框架主要由引擎(Engine)、调度器(Scheduler)、下载器(Downloader)、Spiders、Item Pipelines、下载器中间件(Downloader Middlewares)、Spider中间件(Spider Middlewares)这7个组件构成。

引擎:负责控制数据流在系统所有组件中的流向,并能在不同的条件下触发相对应的事件。引擎组件相当于爬虫的"大脑",是整个爬虫的调度中心。

调度器:从引擎接收请求并将该请求加入队列,以便之后引擎需要时将它们提供给引擎。初始爬取的URL和后续在网页中获取的待爬取URL都将被放入调度器中,等待爬取,同时调度器会自动去除重复的URL。如果特定的URL不需要去重,那么可以通过设置实现,如POST请求的URL。

下载器:主要功能是获取网页内容,并将其提供给引擎和Spiders。

Spiders:是Scrapy用户编写的用于分析响应,并提取Items或额外跟进的URL的一个类。每个Spider负责处理一个(或一些)特定网站。

Item Pipelines:主要功能是处理被Spiders提取出来的Items。典型的处理有清理、验证及持久化(如将Items存取到数据库中)。当网页中被爬虫解析的数据存入Items后,将被发送到Item Pipelines,经过几个特定的数据处理次序后,存入本地文件或数据库。

下载器中间件:是一组在引擎及下载器之间的特定钩子(Specific Hook),主要功能是处理下载器传递给引擎的响应(Response)。下载器中间件提供了一个简便的机制,可通过插入自定义代码来扩展Scrapy的功能。通过设置下载器中间件可以实现爬虫自动更换User-Agent、IP地址等功能。

Spider中间件:是一组在引擎及Spiders之间的特定钩子,主要功能是处理Spiders的输入(响应)和输出(Items及请求)。同时,Spider中间件提供了一个简便的机制,可通过插入自定义代码来扩展Scrapy的功能。

2、Scrapy框架中各组件之间的数据流向

数据流在Scrapy中由执行引擎控制,其基本步骤如下:

引擎打开一个网站,找到处理该网站的Spiders,并向该Spiders请求第一个要爬取的URL。

引擎将爬取请求(Requests)转发给调度器,调度器指挥进行下一步。

引擎从调度器获取下一个要爬取的请求。

调度器返回下一个要爬取的请求,通过下载器中间件(请求方向)将请求转发给下载器。

当网页下载完毕时,下载器会生成一个该网页的响应,并将其通过下载器中间件(响应方向)发送给引擎。

引擎从下载器中接收到响应并通过Spider中间件(输入方向)发送给Spiders处理。

Spiders处理响应并返回爬取到的Items及(跟进)新的请求给引擎。

引擎将爬取到的Items(Spiders返回的)给Item Pipelines,将请求(Spiders返回的)给调度器。

重复步骤(2)直至调度器中没有更多的URL请求,引擎关闭该网站。

3、熟悉Scrapy常用命令

Scrapy通过命令行进行控制,Scrapy提供了多种命令,用于多种目的,并且每个命令都接收一组不同的参数和选项。

除了全局命令外,Scrapy还提供了专用于项目的项目命令。

在使用Scrapy爬虫框架的过程中,常用的命令主要是全局命令中的startproject、genspider、runspider,以及项目命令中的crawl、list。

二、通过Scrapy爬取文本信息

1、创建Scrapy爬虫项目

使用Scrapy框架进行网页数据爬取的第一步就是启动爬虫,使用Scrapy提供的startproject命令即可创建一个爬虫项目,其基本语法格式如下:

打开PyCharm,在"Terminal"(终端)运行"scrapy startproject TipDMSpider D:\项目7\code"命令,即可在目录"E:\mypython\code"下,创建一个名为"TipDMSpider"的Scrapy爬虫项目。

创建完成后,在"E:\mypython\code"下即可生成一个名为TipDMSpider的文件夹和scrapy.cfg文件。

需要用户自定义的目录与脚本文件的名称、作用如下表。

2、修改items/pipelines脚本

爬虫的主要目标是从网页非结构化的数据源中提取结构化的数据。

TipDMSpider项目最终的目标是解析出文章的标题(title)、时间(time)、正文(text)、浏览数(view_count)等数据。

Scrapy提供了Item对象来完成将解析数据转换为结构化数据的功能。

Item对象是一种简单的容器,用于保存爬取到的数据,它提供了类似于字典的API,以及用于声明可用字段的简单语法。

Item可使用简单定义语法及Field对象来声明。新建的TipDMSpider项目中的items脚本模板如下,用于定义存储数据的Item类,该类继承于scrapy.Item。

python 复制代码
import scrapy
class TipdmspiderItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    pass

根据TipDMSpider项目的目标,对items脚本进行定制。TipdmspiderItem类如代码所示。

python 复制代码
class TipdmspiderItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()
    text = scrapy.Field()
    time = scrapy.Field()
    view_count = scrapy.Field()

Items将会流向Item Pipelines。Item Pipelines的作用是将获取到的数据持久化,其主要内容如下。

清理爬取到的数据。

验证爬取数据的合法性,检查Items是否包含某些字段。

保存数据至文件或数据库中。

值得注意的是,每个Item Pipelines都是一个独立的Python类,必须实现process_item()方法。每个Item Pipelines组件都需要调用process_item()方法,该方法必须返回一个Item对象,或抛出DropItem异常,被丢弃的Item将不会被之后的Pipelines组件所处理。

在新建的TipDMSpider项目中,自动生成的Item pipelines脚本模板如下。

python 复制代码
from itemadapter import ItemAdapter
class TipdmspiderPipeline:
    def process_item(self, item, spider):
        return item

在pipelines脚本模板的process_item()方法中,除"self"参数外,还存在item和spider这两个参数,根据TipDMSpider项目的目标,对items脚本进行定制。

TipDMSpider项目提取的信息最终将存储至CSV文件或数据库中。使用pandas库将Items中的数据转换为DataFrame结构会更方便处理。

pandas库的DataFrame类的基本语法格式如下:

Items中的数据转换为DataFrame结构后即可使用to_csv()方法轻松地将数据存储至CSV文件中。to_csv()方法的基本语法格式如下:

还可以使用to_sql()方法将数据存储至数据库中。

需要注意的是,对数据库进行操作需要使用数据连接相关的工具,在项目3中已经介绍了使用PyMySQL库操作数据库,但to_sql()方法需要配合sqlalchemy库中的create_engine函数才能顺利使用。

create_engine函数可用于创建一个数据库连接,其主要参数是一个连接字符串,MySQL和Oracle数据库的连接字符串的格式如下。

数据库产品名+连接工具名://用户名:密码@数据库IP地址:数据库端口号/数据库名称?charset = 数据库数据编码

配合pandas库,修改pipelines脚本。

3、编写spider脚本

创建TipDMSpider项目后,爬虫模块的代码都放置于spiders目录中。创建之初,spiders目录下仅有一个"init.py"文件,并无其他文件,对于初学者而言极有可能无从下手。

使用genspider命令,可以解决这一问题,genspider命令的基本语法格式如下。

在PyCharm的"Terminal"中,使用"cd D:/项目7/code/TipDMSpider"命令进入Scrapy爬虫项目目录后,再运行"scrapy genspidertipdm www.tipdm.com"命令即可创建一个spider脚本模板。

spider脚本模板创建后,在spiders目录下会生成一个tipdm脚本模板。

在TipDMSpider项目目录下运行crawl命令即可启动爬虫,crawl命令的基本语法格式如下。

在PyCharm的"Terminal"中运行"scrapy crawl tipdm"命令。

在tipdm脚本中,parse()方法负责解析返回的数据并提取数据,以及生成需要进一步处理的URL的Reponse对象。

在此之前,需要根据爬取目标设计网页爬取的流程。本次爬取的目标是网站"http://www.tipdm.com"中的"新闻中心"页面中所有的信息。

在TipdmSpider类的parse()方法中,其中一个参数是response,对传入的响应直接使用XPath和CSS方法即可根据对应的规则解析网页。

要在TipDMSpider项目中使用XPath进行网页解析,首先需要分析摘要网页URL的规律。

通过规律能够较快获得所有的摘要网页的URL,从图所示的网页源代码可以看出,从第2页开始,网页的URL中发生改变的是index与html之间的网页编号,例如,第2页的网页URL后面部分是index_2.jhtml,第3页则是index_3.jhtml。

故获得总共的网页数目,即可知道所有摘要网页的网址。

获得"新闻中心"网页数目所在的节点信息的XPath为"//*[@id="t505"]/div[6]/div/a[6]/text()"

同时由于第1页网址与其他页网址规则不同,所以需要手动添加。

由于parse()方法默认响应start_urls中的网址,同时不同网页需要解析的内容不同,所以后续的解析需要通过调用其他方法来实现,代码中的最后一行使用了Scrapy中http包下的Request类用于回调。

Request类的基本语法格式如下:

Request类的回调方法的作用是获取所有文章网页网址,分析网页源代码可以获取所有文章网页网址的XPath,即"//*[@id="t505"]/div/div[3]/h1/a/@href"。

同时需要注意获取的网页网址并非一个完整的网址,还需要将每个网址补充完整。

TipDMSpider项目的最终目标是获取文章的标题、时间、正文、浏览数,在获取了文章的网址之后,对文章网页进行解析即可得到对应的内容。解析文章相关信息的XPath如下表所示。

如果正文存在分段的现象,那么在解析的过程中会将不同的段落放在同一个list中,为了保证存储方便,需要将list中的信息进行合并。

同时,需要将所有解析出来的信息均存放至item中。

ipDMSpider项目的spider脚本已基本编写完成,但需要注意,由于在parse()、parse_url()两个方法中调用了Request类,在parse_text()方法中调用了item,所以需要在创建的spider脚本最前端加入导入Request类和TipDMSpider项目构建的Item类的代码,完成添加后的spider脚本的所有导入函数与类的语句,如代码所示。

python 复制代码
import scrapy
from scrapy.http import Request
from TipDMSpider.items import TipdmspiderItem

4、修改settings脚本

Scrapy设置允许自定义所有Scrapy组件,包括核心、扩展、管道和爬虫本身。

设置的基础结构可提供键值映射的全局命名空间,代码可以使用它,并从全局命名空间提取配置值。

用户可以通过不同的机制来填充设置,这些设置也是选择当前活动的Scrapy项目的机制之一。

在TipDMSpider项目的默认settings脚本中共有25个设置。

(续上表)

(续上表)

TipDMSpider项目中需要修改的设置分别为ROBOTSTXT_OBEY、DOWNLOAD_DELAY、ITEM_PIPELINES、HTTPCACHE_ENABLED、HTTPCACHE_DIR。

在PyCharm的"Terminal"中运行"scrapy crawl tipdm"命令运行项目。

三、定制下载器中间件

任务描述:

下载器中间件位于引擎和下载器之间。

引擎将未处理的请求发送给下载器的时候,会经过下载器中间件,这时在中间件里可以包装请求,如修改请求头信息(设置User-Agent、Cookie等)和添加代理IP地址。

当下载器将网站的响应发送给引擎时,也会经过下载器中间件,此时即可对响应内容进行处理。

任务分析:

编写下载器中间件脚本。

激活下载器中间件。

1、编写下载器中间件脚本

每个中间件组件都是一个Python类,下载器中间件定义了process_request()、process_response()、process_exception()中的一种或多种方法。

process_request()方法将会被所有通过下载器中间件的每一个请求调用,具有request和spider两个参数,参数说明如表所示。

process_request()方法的返回值有4种类型,每种返回值类型的说明如表所示。

下载器中间件常用于防止爬虫被网站的反爬虫规则所识别。通常绕过这些规则的常见方法如下。

动态设置User-Agent,随机切换User-Agent,模拟不同用户的浏览器信息。

禁用Cookie,也就是不启用CookiesMiddleware,不向服务器发送Cookie。有些网站通过Cookie的使用来发现爬虫行为,可以通过COOKIES_ENABLED控制CookiesMiddleware的开启和关闭。

设置延迟下载,防止访问过于频繁,设置延迟时间为2s或更高,可以通过DOWNLOAD_DELAY控制下载频率。

下载器中间件常用于防止爬虫被网站的反爬虫规则所识别。通常绕过这些规则的常见方法如下。

使用百度等搜索引擎服务器网页缓存获取的网页数据。

使用IP地址池,现在大部分网站都是根据IP地址来判断是否为同一访问者的。

使用Crawlera(专用于爬虫的代理组件),正确配置Crawlera和下载器中间件后,项目所有的请求都可通过Crawlera发出。

从实现难度上看,比较容易实现的方法是(1)、(2)、(3)、(5),其中,(2)与(3)通过修改settings脚本即可实现,另外两种则是使用process_request()方法随机选择访问网页的User-Agent与随机切换访问IP地址来实现的。

在TipDMSpider项目的middlewares脚本下创建下载器中间件,实现(1)、(5)两种方法。

除了定制下载器中间件外,在Scrapy框架中已经默认提供并开启了众多下载器中间件,在内置的下载器中间件中,DOWNLOADER_MIDDLEWARES_BASE设置的各中间件说明及其顺序如表所示。

(续上表)

激活下载器中间件组件,需要将其加入settings脚本下的DOWNLOADER_MIDDLEWARES设置中。

这个设置是一个字典(dict),键为中间件类的路径,值为其中间件的顺序(order),同时会根据顺序值进行排序,最后得到启用中间件的有序列表,即第一个中间件最靠近引擎,最后一个中间件最靠近下载器。

激活TipDMSpider项目中middlewares目录下创建的下载器中间件。

在settings脚本中,对DOWNLOADER_MIDDLEWARES设置进行修改后,会与Scrapy内置的下载器中间件设置DOWNLOADER_MIDDLEWARES_BASE合并,但并不会覆盖。

若要取消Scrapy默认在DOWNLOADER_MIDDLEWARES_BASE中打开的下载器中间件,可在DOWNLOADER_MIDDLEWARES中将该中间件的值设置为0。

如果需要关闭RobotsTxtMiddleware,那么需要在DOWNLOADER_MIDDLEWARES设置中将该中间件的值设置为0。

2、定制Spider中间件

在Scrapy中自带Spider中间件,通过激活Spider中间件可以获取到Item,即爬取数据的封装结构。

Spider中间件位于Spiders(程序)和引擎之间,在Item即将达到Item Pipeline之前,对Item和响应进行处理。

Spider中间件是介入Scrapy中的Spiders处理机制的钩子框架,可以在其中插入自定义功能来处理发送给Spiders的响应,以及Spiders产生的Items和请求。

Spider中间件定义了process_spider_input()、process_spider_output()、process_spider_exception()、process_start_requests()中的一种或多种方法。

根据Spider中间件的功能不同,需要用到的方法也不同,很多时候,Scrapy默认提供并开启的Spider中间件就已经能够满足多数需求。

在内置的Spider中间件中,SPIDER_MIDDLEWARES_BASE设置的中间件说明及其顺序如表所示。

激活Spider中间件组件的方法与激活下载器中间件的方法基本相同,需要将定制的Spider中间件加入settings脚本下的SPIDER_MIDDLEWARES设置中。

这个设置同样是一个字典,键为中间件类的路径,值为其中间件的顺序,同时会根据顺序值进行排序,最后得到启用中间件的有序列表,即第一个中间件最靠近引擎,最后一个中间件最靠近Spiders。

另外,针对Spider中间件,Scrapy同样内置了中间件设置SPIDER_MIDDLEWARES_ BASE,该设置也不能覆盖,在启用时会结合SPIDER_MIDDLEWARES设置。

若要取消Scrapy默认在SPIDER_MIDDLEWARES_BASE中打开的Spider中间件,同样需要在SPIDER_MIDDLEWARES设置中将中间件的值设置为0,如代码所示。

python 复制代码
SPIDER_MIDDLEWARES = {
    'scrapy.spidermiddlewares.referer.RefererMiddleware': 0,
}

更多精彩内容请关注本站!

相关推荐
哇咔咔哇咔4 分钟前
【科普】conda、virtualenv, venv分别是什么?它们之间有什么区别?
python·conda·virtualenv
infiniteWei5 分钟前
【Lucene】什么是全文检索?解读结构化数据与非结构化数据
django·全文检索·lucene
CSXB9926 分钟前
三十四、Python基础语法(文件操作-上)
开发语言·python·功能测试·测试工具
亚图跨际1 小时前
MATLAB和Python及R潜变量模型和降维
python·matlab·r语言·生物学·潜变量模型
infiniteWei1 小时前
【Lucene】全文检索 vs 顺序扫描,为何建立索引比逐个文件搜索更高效?
django·全文检索·lucene
IT古董1 小时前
【机器学习】决定系数(R²:Coefficient of Determination)
人工智能·python·机器学习
德育处主任Pro1 小时前
『Django』APIView基于类的用法
后端·python·django
Star Patrick2 小时前
算法训练(leetcode)二刷第十九天 | *39. 组合总和、*40. 组合总和 II、*131. 分割回文串
python·算法·leetcode
武子康3 小时前
大数据-213 数据挖掘 机器学习理论 - KMeans Python 实现 距离计算函数 质心函数 聚类函数
大数据·人工智能·python·机器学习·数据挖掘·scikit-learn·kmeans
写点什么啦3 小时前
使用R语言survminer获取生存分析高风险和低风险的最佳截断值cut-off
开发语言·python·r语言·生存分析·x-tile