引言:Scrapy是Python开发的一个快速、高层次的屏幕抓取和web抓取框架用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。

一、Scrapy架构的来源与详解

首先,框架的作用本质是将一堆轮子融合在一起,可以方便快速的解决一类问题。
最初,我们在入门学习爬虫使用requests库时,一套基本的爬取网页内容流程如下:

基本流程伪代码如下:

import requests
from lxml import etree// 1.URL队列
urls = ['https://aaai.org/ocs/index.php/AAAI/AAAI18/paper/viewPaper/16488','https://aaai.org/ocs/index.php/AAAI/AAAI18/paper/viewPaper/16583',...
]
data = []
for url in urls:// 2.发送请求response = requests.get(url)  html = response.content       // 获取网页内容(content返回的是bytes型数据,text()获取的是Unicode型数据)// 3.内容提取title = etree.HTML(html).xpath('//*[@id="title"]/text()') // 4.数据队列data.append(title)
// 保存数据.....

而以上流程基本在爬取过程中是固定不变的,因此诞生了Scrapy爬虫框架,用来整合上面的每一步骤,用户无需编写每一步的代码,仅需要改写需要自定义的模块即可。下图为Scrapy架构图:

【注意】:于上图基本流程不同的是,从爬虫➡️调度器,以及调度器➡️下载器不再以URL传递,而是以封装好的Requests请求传递
下面为Scrapy各个组件的功能介绍:

组件 功能 是否实现
Scrapy Engine(引擎) 总指挥:负责不同模块间数据的传递 已实现
Scheduler(调度器) 一个存放引擎发过来的request请求队列 已实现
Downloader(下载器) 下载从引擎发过来的requests请求,并返回给引擎 已实现
Downloader Middlewares
(下载中间件)
可自定义的下载扩展,比如设置代理 可选改写
Spider(爬虫) 处理引擎发来的response
1⃣️提取数据,交给引擎传输到管道进行处理和存储
2⃣️提取URL
,组装成requests请求并从引擎传输到调度器
需手写
Spider Middlewares
(爬虫中间件)
可自定义requests请求进行response过滤 可选改写
Item Pipeline(管道) 处理引擎传过来的数据,比如存储 需手写

【注意】:使用Scrapy爬虫框架,可提升可靠性,低耦合,因为以上模块相关且独立,若其中一个模块出错,则不影响其他模块的运行。

二、Scrapy模块的安装与初始配置

2.1 安装Scrapy
$ pip install scrapy
2.2 创建Scrapy项目
$ scrapy startproject <projectName>

创建成功后根据终端提示进入项目目录:

$ cd <projectName>
2.3 生成Scrapy爬虫
$ scrapy genspider <spiderName> <domin>

以上命令需要两个参数,分别是自定义的爬虫名(即新建.py爬虫文件的名字),以及要爬取网址的域名
例如要爬取百度中的某一页面就可以写成如下格式:

$ scrapy genspider baidu baidu.com
2.4. 执行Scrapy爬虫
$ scrapy crawl <spiderName>
2.5. 使用Scrapy Shell

在未启动Scrapy爬虫的情况下,可以使用shell进行debug和测试:

$ scrapy shell <爬取网站网址>
2.6 修改Scrapy项目settings.py文件

在编写爬虫代码前,我们需要先修改配置文件:

如上图,我们需要设置USER_AGENT为自己浏览器的代理,表示我们模拟浏览器登录。然后我们进行如下设置:

ROBOTSTXT_OBEY = False    # 不遵循爬虫协议
LOG_LEVEL = 'WARN'        # 设置日志级别为'WARN',则仅打印警告以上级别的日志

日志的四个级别优先级由高到低分别是:

  • ERROR
  • WARN
  • INFO
  • DEBUG

同时,还有解除ITEM_PIPELINES注释,如下图:

该配置项表示可以使用管道,后面的值表示距离,即优先级,值越小,管道距离越近,优先执行距离近的管道。如下,优先执行MyspiderPipeline1,然后在执行MyspiderPipeline

ITEM_PIPELINES = {'mySpider.pipelines.MyspiderPipeline': 300,'mySpider.pipelines.MyspiderPipeline1': 299,
}

以下通过文件树列出创建后的scrapy项目文件,并注释了主要文件的功能:

$ tree
.
├── mySpider
│   ├── __init__.py
│   ├── __pycache__
│   ├── items.py         # 自定义需要爬取的内容
│   ├── middlewares.py   # 下载中间件+爬虫中间件,可自定义
│   ├── pipelines.py     # 管道,用于数据保存
│   ├── settings.py      # 设置文件,如代理、日志级别等
│   └── spiders
│       ├── __init__.py
│       ├── __pycache__
│       └── itcast.py    # 生成的爬虫文件
└── scrapy.cfg

三、基本代码入门

在Scrapy框架中,我们至少需要修改爬虫管道文件以实现最基本的爬虫。

3.1 编辑爬虫文件

在上一步生成Scrapy爬虫后可在新建项目的spiders文件夹下看到爬虫文件,如下图。此时,需要将start_urls修改为自己最开始要爬取的页面URL,并在parse函数中编写页面解析代码,此处使用response自带的XPath方法选取节点。[不懂XPath的用法见此]

由于xpath返回的文本内容Selector特殊列表,因此我们还需要使用extract()extract_first()函数提取数据文本内容,具体代码如下:

class ItcastSpider(scrapy.Spider):name = 'itcast'                                               # 爬虫名allowed_domains = ['itcast.cn']                               # 允许爬取的范围start_urls = ['http://www.itcast.cn/channel/teacher.shtml']   # 最开始请求的URL地址def parse(self, response):    # 数据提取方法,接收来自下载中间件传来的response// 分组li_list = response.xpath('//div[@class="tea_con"]//li') # xpath返回含有selector对象的列表for li in li_list:item = {}item['name'] = li.xpath('.//h3/text()').extract()[0]item['title'] = li.xpath('.//h40/text()').extract_first()yield item

此处,笔者强烈建议使用extract_first()函数,其等价于extract()[0],主要优点是如果提取出空字符串,则返回None而不是空列表,这里使得我们无需再判断是否为空!

最后使用关键字yield进行中断返回值,相比return优点在于,借用生成器特点逐个返回值从而减少内存占用

此处返回值类型必须如下,如果是列表则会报错

返回值类型 Request(向调度器传) BaseItem dict(向管道传) None
3.2 编辑管道文件

管道文件是pipelines.py,此处使用MongoDB保存爬取的数据[Python安装并操作MongoDB见此]:

// pipelines.py
from pymongo import MongoClientclient = MongoClient('127.0.0.1', 27017)
db = client.LaGou
col = db.infoclass LagouPipeline(object):def process_item(self, item, spider):col.insert_many([item])return item

以上便可实现最基本的爬取数据入库的流程,方便理解,以下将进行完整爬虫项目。

四、实战Scrapy之阳光政务平台爬虫项目

【项目描述】:爬取「东莞阳光热线问政平台」中的投诉标题、申诉部门、处理状态、发布时间、详情页面中的投诉文本内容以及图片。
【网站地址】:东莞阳光热线问政平台
【完整项目代码】:我的GitHub.



【爬取结果】:
以下为本项目的主要模块代码,已在必要的地方做了详细注释:

4.1 爬虫文件
//  spiders/yg.py
import scrapy
import random
from YangGuang.items import YangguangItemclass YgSpider(scrapy.Spider):name = 'yg'allowed_domains = ['sun0769.com']start_urls = ['http://wz.sun0769.com/index.php/question/questionType?type=4&page=0']def parse(self, response):'''首页解析函数'''tr_list = response.xpath('//div[@class="greyframe"]/table[2]//tr')headers = {'User-Agent': self.get_ua()}for tr in tr_list:item = YangguangItem()item['title'] = tr.xpath('.//a/@title').extract_first()item['department'] = tr.xpath('.//a[@class="t12h"]/text()').extract_first()item['status'] = tr.xpath('.//td[3]/span/text()').extract_first()item['publish_date'] = tr.xpath('.//td[last()]/text()').extract_first()item['href'] = tr.xpath('.//a[@class="news14"]/@href').extract_first()yield scrapy.Request(url=item['href'],callback=self.parse_detail,  # 指定传入的URL由parse_detail解析函数处理meta={'item':item},          # 向parse_detail传递的元数据headers=headers,             # 传入包含随机UA的headers)next_url = response.xpath('//div[@class="pagination"]/a[text()=">"]/@href').extract_first()if next_url is not None:yield scrapy.Request(url=next_url,callback=self.parse,)def parse_detail(self, response):'''详情页面解析函数'''item = response.meta['item']  # 取出从parse传来的元数据img = response.xpath('//div[@class="textpic"]/img/@src').extract_first()  # 获取详情页面的图片地址(不含域名)if img is None: # 若获取图片地址失败,则1.该页面仅有文本内容;2.该页面不存在-404item['img'] = Noneitem['contentext'] = response.xpath('//div[@class="wzy1"]//tr[1]/td[@class="txt16_3"]/text()').extract()else:   # 若成功获取图片地址,加上域名前缀,且文本内容xpath如下item['img'] = 'http://wz.sun0769.com'+imgitem['contentext'] = response.xpath('//div[@class="contentext"]/text()').extract()yield itemdef get_ua(self):'''随机生成User-Agent用户代理'''first_num = random.randint(55, 76)third_num = random.randint(0, 3800)fourth_num = random.randint(0, 140)os_type = ['(Windows NT 6.1; WOW64)', '(Windows NT 10.0; WOW64)', '(X11; Linux x86_64)','(Macintosh; Intel Mac OS X 10_14_5)']chrome_version = 'Chrome/{}.0.{}.{}'.format(first_num, third_num, fourth_num)ua = ' '.join(['Mozilla/5.0', random.choice(os_type), 'AppleWebKit/537.36','(KHTML, like Gecko)', chrome_version, 'Safari/537.36'])return ua
4.2 管道文件
// pipelines.py
import re
from YangGuang.settings import MONGO_HOST, MONGO_PORT
from pymongo import MongoClientclass YangguangPipeline(object):def open_spider(self, spider):'''爬虫开始执行时执行的函数(仅run一次),可放入数据库连接代码'''client = MongoClient(MONGO_HOST, MONGO_PORT)  # 新建MongoDB客户端实例self.col = client['YangGuang']['content']     # 新建数据库为YangGuang,集合为content的实例def process_item(self, item, spider):item['contentext'] = self.process_content(item['contentext']) # 清洗item中content数据self.col.insert_many([dict(item)])     # 向MongoDB中插入数据# print(item['href'])return itemdef process_content(self, content):'''对content数据进行清洗,去除空白字符等不必要的数据'''if content == []:  # 如果content是空列表,说明详细页面响应404return None# 使用列表切片和sub替换,逐个清洗数据中的空格、\t、\n和\xa0等任意空白字符content = [re.sub('\s', '', item) for item in content]# 将含有多个字段的列表连接成只有一个字段的列表content = ''.join(content)return content
4.3 项目文件
// items.py
import scrapyclass YangguangItem(scrapy.Item):title = scrapy.Field()        # 标题department = scrapy.Field()   # 负责部门status = scrapy.Field()       # 处理状态publish_date = scrapy.Field() # 发布时间href = scrapy.Field()         # 详情页面超链接contentext = scrapy.Field()   # 详情页面投诉文本内容img = scrapy.Field()          # 详情页面投诉图片内容

【参考文献】:
[1] XPath常用语法总结及应用.
[2] 东莞阳光热线问政平台.

Scrapy爬虫框架的原理与实战[阳光政务爬虫项目]相关推荐

  1. python可视化爬虫框架_8个最高效的Python爬虫框架

    1.Scrapy Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中..用这个框架可以轻松爬下来如亚马逊商品信息之类的 ...

  2. 基于JavaGUI+Web Magic爬虫框架实现的医案采集系统 毕业文档+项目源码

    资源下载地址:https://download.csdn.net/download/sheziqiong/85695155 资源下载地址:https://download.csdn.net/downl ...

  3. 最新后盾网Laravel框架重入门到实战 Laravel博客项目实战 陈华主讲 包含课件源码

    老师介绍 陈华,PHP明星讲师,大学生演讲网创始人,2010年开始开发整站项目,精通Laravel,Yii框架. 简 介 本套课程是一套以项目实战为主的Laravel5.2实战开发教程,是真正意义上的 ...

  4. python爬虫框架怎么安装_celery如何在python爬虫中安装?

    在我们学习了不少关于celery框架的知识后,很多小伙伴已经想要正式使用celery了.这里小编也不知道大家安装好了celery没有~为了照顾一下动手能力不太强的python小白,小编把celery框 ...

  5. python爬虫技术可以干什么-Python实战:网络爬虫都能干什么?

    整站下载器:siteSucker https://blog.csdn.net/l_215851356/article/details/54377582 http://python.jobbole.co ...

  6. python爬虫开发 从入门到实战_python网络爬虫从入门到实战开发

    1.简单的抓取网页 from urllib import request req=request.Request("http://www.baidu.com") response= ...

  7. python爬虫框架——scrapy(1)scrapy爬虫框架介绍

    导语:(python语言中存在众多的爬虫框架,本文及接下来的几篇都只介绍scrapy框架) 一:整理scrapy爬虫框架组件的各种知识,了解爬虫机制的原理 1.scrapy架构: 各个组件: 引擎(E ...

  8. 第五章 Scrapy爬虫框架(5.1 Scrapy框架基础)

    Scrapy是一个高级Web爬虫框架,用于爬取网站并从页面中提取结构化数据.它可以用于数据挖掘.数据监控和自动化测试等多个方面.与之前讲过的Requests库和Selenium库不同,Scrapy更适 ...

  9. 网络爬虫框架Scrapy简介

    作者: 黄进(QQ:7149101) 一. 网络爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本:它是一个自动提取网页的程序,它为搜索引擎从万维 ...

  10. Python 网络爬虫笔记2 -- Requests库实战

    Python 网络爬虫笔记2 – Requests库实战 Python 网络爬虫系列笔记是笔者在学习嵩天老师的<Python网络爬虫与信息提取>课程及笔者实践网络爬虫的笔记. 课程链接:P ...

最新文章

  1. 先进先出置换算法(FIFO)
  2. 回过头来看对象的四种状态强软弱虚引用的理解
  3. python字典通过键值获取键名,通过value获取key
  4. 分布式表格系统Google Bigtable详解
  5. ubuntu16.04 安装docker-ce,解决libltdl7版本过低的问题
  6. DataList控件分页
  7. 《netty入门与实战》笔记-02:服务端启动流程
  8. python找人_python之找最后一个人
  9. Android系统(23)---Android 应用分屏
  10. java part.inlimen_java字符串加密及动手动脑
  11. win2003域迁移实战记录
  12. leetcode 动态规划 —— 53(最大子序列的和)
  13. c语言void nzp,二级C语言考试辅导教程第五章:函数[5]
  14. 未解决:运行EtherCalc出错:Error: Cannot find module 'zappajs'
  15. 二分查找算法(Java)
  16. C++ 动态库、静态库、__declspec(dllexport)、符号隐藏、gcc visibility (“default“)
  17. 编写程序,先将输入的一系列整数中的最小值与第一个数交换,然后将最大值与最后一个数交换,最后输出交换后的序列。
  18. ictclas4j java_使用继续完善前人写的文章:使用ICTCLAS JAVA版(ictclas4j)进行中文分词...
  19. docker安全配置(cpu、分区的大小设定和权限设定)
  20. NS3 Tutorial 中文版:第三章 快速上手

热门文章

  1. 车载GPS设备对接java记录
  2. cad打开卡死_CAD点打开或者保存就卡死无响应的解决方法
  3. 《第一篇》二进制部署高可用K8S集群v1.24.2及运维(亲测无坑)
  4. 计算机室火灾隐患表现,消防控制室存在的火灾隐患及对策
  5. matlab 填充透明色,在Matlab中使用透明像素填充数组
  6. 项目组织对ERP软件实施的影响
  7. 51单片机最小系统的c语言,89c51单片机最小系统,89c51最小系统原理图的功能详解...
  8. 基于python的手机销售系统
  9. (转载)一套键鼠控制多台电脑操作——Synergy软件(windows环境)
  10. 无人车系统(七):Udacity ‘s无人驾驶仿真环境(社区介绍)