scrapy框架
1. scrapy框架简介
2.scrapy框架
1. 整体架构
Scrapy 使用了 Twisted异步网络库来处理网络通讯。整体架构大致如下

2. Scrapy主要包括了以下组件:
Scrapy Engine(引擎):
负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。
用来处理整个系统的数据流处理,触发事务(加载核心)。
Scheduler(调度器):
它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。
用来接受引擎发过来的请求,压入队列中,并在引擎再次请求的时候返回,可以想象成一个url(抓取网页的网址或者说是链接)的优先队列,由它来绝对下一个要抓取的网址是什么,同时去除重复的网址
Downloader(下载器):
负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理。
用于下载网页内容,并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
Spider(爬虫):
它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器)。
爬虫是主要干活的,用于从特定的网页中提取自己需要的信息,即所谓的实体(Item).用户也可以从中提取链接,让Scrapy继续抓取下一个页面
Item Pipeline(管道):
它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方。
负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
Downloader Middlewares(下载中间件):
一个可以自定义扩展下载功能的组件。
Spider Middlewares(Spider中间件):
一个可以自定扩展和操作引擎和Spider中间通信的功能组件。
3. Scrapy运行流程大概如下:
- 引擎从调度器中取出一个链接(URL)用于接下来的抓取
- 引擎把URL封装成一个请求(Request)传给下载器
- 下载器把资源下载下来,并封装成应答包(Response)
- 爬虫解析Response
- 解析出实体(Item),则交给实体管道进行进一步的处理
- 解析出的是链接(URL),则把URL交给调度器等待抓取
3. scrapy框架集成的功能
- 高性能的数据解析操作(xpath)
- 高性能的数据下载
- 高性能的持久化存储
- 中间件
- 全栈数据爬取操作
- 分布式:redis
- 请求传参的机制(深度爬取)
- scarpy中合理的应用selenium
4. 环境安装
1. linux和max上的安装
pip3 install scrapy
2. window上的安装
# 1.安装wheel
1.pip3 install wheel
# 2.下载twisted
http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
# 3.安装twisted
进入下载目录,执行pip3 install Twisted?17.1.0?cp35?cp35m?win_amd64.whl
# 4.安装pywin32
pip3 install pywin32
# 5.安装scrapy
pip3 install scrapy5.创建工程
# 在pyCharm的终端执行 # 切换到当前目录下 cd scrapy_practice # 创建一个项目 scrapy startproject proname # 切换到当前项目文件目录下 cd proname # 创建爬虫文件 scrapy genspider spidername www.xxx.com # 执行命令爬虫的文件 scrapy crawl spidername # settings配置文件 1.默认是遵从robots协议的,ROBOTSTXT_OBEY = True改为False,就不遵从robots协议 2.UA伪装 3.LOG_LEVEL = "ERROR" # 修改日志的输出等级,让日志值输出错误信息
爬虫文件的初始
import scrapy
class FirstSpider(scrapy.Spider):
# 爬虫文件的名称;爬虫源文件的唯一标识
name = "first"
# 允许的域名:就是对起始的url列表进行限制(通常情况下都会注释)
allowed_domains = [‘www.xxx.com‘] # 起始的url列表:列表中的列表元素会被scrapy自动的进行请求发送,可以存放多个
start_urls = [‘http://www.xxx.com/‘,‘http://www.xxx2.com/‘]# 解析数据
def parse(self, response):
print(response)6. scrapy的数据解析
extract():列表是有多个列表元素 extract_first():列表元素只有单个
import scrapy
class FirstSpider(scrapy.Spider):
# 爬虫文件的名称:爬虫源文件的唯一标识
name = ‘first‘
# 允许的域名:
allowed_domains = [‘www.baidu.com‘]
#起始的url列表:列表中的列表元素会被scrapy自动的进行请求发送
start_urls = [‘https://dig.chouti.com/‘]
#解析数据
def parse(self, response):
div_list = response.xpath(‘/html/body/main/div/div/div[1]/div/div[2]/div[1]‘)
for div in div_list:
# 注意:xpath返回的列表中的列表元素是Selector对象,我们要解析获取的字符串的数据是存储在该对象中必须经过一个extract()的操作才可以将改对象中存储的字符串的数据获取
# content = div.xpath(‘./div/div/div[1]/a/text()‘)[0].extract()
content = div.xpath(‘./div/div/div[1]/a/text()‘).extract_first()
# xpath返回的列表中的列表元素有多个(Selector对象),想要将每一个列表元素对应的Selector中的字符串取出改如何操作?response.xpath(‘/div//text()‘).extract()
print(content) # <Selector xxx=‘dsdsd‘ data="短发hi的说法绝对是">7.serapy的持久化存储
1.基于终端指令
只可以将parse方法的返回值存储到磁盘文件中
# 返回值的数据统一写入当前file.csv文件中,如果文件不存在就会新建文件 scrapy crawl first -o file.csv # 对文件的后缀有限制,支持的文件后缀有:(‘json‘, ‘jsonlines‘, ‘jl‘, ‘csv‘, ‘xml‘, ‘marshal‘, ‘pickle‘)
import scrapy
class HuyaSpider(scrapy.Spider):
name = ‘huya‘
# allowed_domains = [‘www.xxx.com‘]
start_urls = [‘https://www.huya.com/g/xingxiu/‘]
def parse(self, response):
print(response)
li_list = response.xpath(‘//*[@id="js-live-list"]/li‘)
dic_list = []
for li in li_list:
title = li.xpath(‘./a[2]/text()‘).extract_first()
authod = li.xpath(‘./span/span[1]/i/text()‘).extract_first()
hot = li.xpath(‘./span/span[2]/i[2]/text()‘).extract_first()
dic = {
"title": title,
"authod": authod,
"hot": hot,
}
dic_list.append(dic)
return dic_list
# 在终端命令输出 D:\practice\crawler_practice\scrapy框架的应用\huyaproject>scrapy crawl huya -o huya.csv2.基于管道:pipelines.py
编码流程:
- 数据解析
- 在item的类中定义相关的属性
- 将解析的数据存储封装到item类型的对象中 .item["属性"]
- 将item对象提交给管道
- 遭管道类中的process_item方法负责接收item对选,然后对item进行任意形式的持久化存储
- 在配置文件中开启管道

细节补充:
- 管道文件中的一个管道了表示将数据存储到某一种形式的平台
- 如果管道文件中定义了多个管道类,爬虫类提交的item会给优先级最高的管道类。(数字越小,优先级越高)
- process_item方法的实现中的return item的操作表示将item传递给下一个即将被执行的管道类。
# huya.py
import scrapy
from huyaPro.items import HuyaproItem
class HuyaSpider(scrapy.Spider):
name = ‘huya‘
# allowed_domains = [‘www.xxx.com‘]
start_urls = [‘https://www.huya.com/g/xingxiu‘]
def parse(self, response):
li_list = response.xpath(‘//*[@id="js-live-list"]/li‘)
for li in li_list:
title = li.xpath(‘./a[2]/text()‘).extract_first()
author = li.xpath(‘./span/span[1]/i/text()‘).extract_first()
hot = li.xpath(‘./span/span[2]/i[2]/text()‘).extract_first()
# 实例化item类型的对象
item = HuyaproItem()
item[‘title‘] = title
item[‘author‘] = author
item[‘hot‘] = hot
yield item # 提交给管道
# items.py
import scrapy
class HuyaproItem(scrapy.Item):
# define the fields for your item here like:
title = scrapy.Field() # Field是一个万能的数据类型(可以任意类型的数据)
author = scrapy.Field()
hot = scrapy.Field()
# pipeline.py
import pymysql
from redis import Redis
# 写入文件中
class HuyaprojectPipeline(object):
fp = None
def open_spider(self,spider):
print("只会在爬虫开始的时候执行一次")
self.fp = open("huyazhibo.txt","w",encoding="utf-8")
def process_item(self, item, spider): # item就是接收到爬虫类提交过来的item对象
self.fp.write(item[‘title‘]+‘:‘+item[‘author‘]+‘:‘+item[‘hot‘]+‘\n‘)
print(item["item"],"写入成功")
return item
def close_spider(self,spider):
print("只会在爬虫结束的时候的调用一次")
self.fp.close()
# 写入mysql数据库中
class mysqlPipeLine(object):
conn = None
cursor = None
def open_spider(self,spider):
self.conn = pymysql.Connect(
host=‘127.0.0.1‘,
port=3306,
user=‘root‘,
password=‘123‘,
db=‘Spider‘,
charset=‘utf8‘)
def process_item(self,item,spider):
sql = ‘insert into huya values("%s","%s","%s")‘%(item[‘title‘],item[‘author‘],item[‘hot‘])
self.cursor = self.conn.cursor()
try:
self.cursor.execute(sql)
self.conn.commit()
except Exception as e:
print(e)
self.conn.rollback()
return item
def close_spider(self,spider):
self.cursor.close()
self.conn .close()
# 写radis数据库中
class RedisPipeLine(object):
conn = None
def open_spider(self,spider):
self.conn = Redis(host=‘127.0.0.1‘,port=6379)
def process_item(self,item,spider):
self.conn.lpush(‘huyaList‘,item)
return item待续