scrapy共分为8部分
Scrapy Engine(引擎): 负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。
Scheduler(调度器): 它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。
Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理,
Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器),
Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方.
Downloader Middlewares(下载中间件):可以自定义扩展下载功能的组件(代理、cokies等)。
Spider Middlewares(Spider中间件):可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)
流程图
scrapy框架如何使用
1.创建一个新的Scrapy项目(scrapy startproject 爬虫项目名称)
2.新建爬虫文件(scrapy genspider 爬虫文件名称 域名 )
打开创建的爬虫文件下的item.py文件item 定义结构化数据字段,用来保存爬取到的数据,有点像Python中的dict,但是提供了一些额外的保护减少错误。可以通过创建一个 scrapy.Item 类, 并且定义类型为 scrapy.Field的类属性来定义一个Item(可以理解成类似于ORM的映射关系)
打开你创建的爬虫文件 里面会有一下代码:
-- coding: utf-8 --
import scrapy
class JobboleSpider(scrapy.Spider):
name = 'jobbole'
allowed_domains = ['jobbole.com']
start_urls = ['http://blog.jobbole.com/all-posts/']
def parse(self, response):
pass
* name = "" :这个爬虫的识别名称,必须是唯一的,在不同的爬虫必须定义不同的名字。
* allow_domains = [] 是搜索的域名范围,也就是爬虫的约束区域,规定爬虫只爬取这个域名下的网页,不存在的URL会被忽略。
* start_urls = () :爬取的URL元祖/列表。爬虫从这里开始抓取数据,所以,第一次下载的数据将会从这些urls开始。其他子URL将会从这些起始URL中继承性生成。
* parse(self, response) :解析的方法,每个初始URL完成下载后将被调用,调用的时候传入从每一个URL传回的Response对象来作为唯一参数,主要作用如下:
* 负责解析返回的网页数据(response.body),提取结构化数据(生成item)
* 生成需要下一页的URL请求。
请求头
response.request.headers
xpath使用
response.xpath(‘xpath路径’)
遵循xpath语法规则
/text() 获取文本
/@属性名 获取属性
extract()
我们解析到的内容被封装在了Selector对象中,需要调用extract()函数将解析的内容从Selecor中取出。返回的是一个list
extract_first('')
我们解析到的内容被封装在了Selector对象中,需要调用extract()函数将解析的内容从Selecor中取出。并返回列表中的第一个元素
css使用
response.xpath(‘css选择器’)
遵循css使用规则
. 表示class
# 表示id
::text 获取标签的文本
::attr(属性名) 获取标签的属性
新增请求
yield scrapy.Request()
url, :要请求的url地址
callback=None, 请求成功的回调函数
method='GET', 设置请求的方式
headers=None, 设置请求头,dict类型
cookies=None, 设置用户的cookies信息 dict类型
meta=None, 传递参数 dict类型
encoding='utf-8', (编码类型,一般不需要改变)
dont_filter=False, (是否过滤url,False表示过滤,True:表示不过滤)
errback=None ,设置请求错误的回调函数
items.py
在这里定义想要获取的字段
例如: title = scrapy.Field()
管道文件
def process_item(self, item, spider):
item:爬虫文件中传递过来的item数据 (是一个对象)
spider: 爬虫文件实例化的对象
def open_spider(self,spider):
def close_spider(self,spider):
def from_crawler(cls,crawler):
def from_settings(cls,settings):
settings.py设置
1. 要在 ITEM_PIPELINES 中激活图片管道
2. IMAGES_STORE 设置图片下载后的存储路径
图片下载管道文件
class MyImagesPipeline(ImagesPipeline):
# def file_path(self, request, response=None, info=None):
# # 可以返回一个图片的路径
# #return 'full/%s.jpg' % (image_guid)
# return 'full/%s.jpg' % (图片的名称)
def get_media_requests(self, item, info):
# 第一步从item中获取要下载的图片地址
# for image_url in item['image_urls']:
# #根据图片的 url地址构建一个Request对象,
# #最终交给调度器
# yield scrapy.Request(image_url)
yield scrapy.Request(item['coverImage'])
def item_completed(self, results, item, info):
#图片请求完毕后会有一个回调结果, item_completed就是
#我们的回调函数,results
image_paths = [x['path'] for status, x in results if status]
if not image_paths:
#丢弃item
raise DropItem("Item contains no images")
else:
#修改图片的文件名称
new_image_paths = []
for img_path in image_paths:
os.rename(image_store + '/' + img_path, image_store + '/' + 'full/' + item['title'] + '.jpg')
new_image_paths.append(image_store + '/' + 'full/' + item['title'] + '.jpg')
#将获取到的图片存储路径赋值给 item
print('66666666666666',new_image_paths)
item['image_paths'] = ','.join(new_image_paths)
return item
pipeline.py 与 items.py 解藕(数据持久化优化方案)
思路:在item类中定义方法返回sql语句和数据,在管道文件中使用item对象进行调用,执行数据插入操作