scrapy框架的简单理解
scrapy框架的简单应用
-
什么是scrapy?
Scrapy是适用于Python的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。
-
scrapy的基本框架
- 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(下载中间件):一个可以自定义扩展下载功能的组件。
- Spider Middlewares(Spider中间件):一个可以自定扩展和操作引擎和Spider中间通信的功能组件。
流程简述:
引擎打开一个域名之后,找到处理这个网站的爬虫,获取start_urls,然后将请求将这些url交给调度器,调度器以requests返回给引擎,引擎再交给下载器下载页面数据,返回response给引擎,引擎将response交给相应的爬虫处理,提取item所需要的数据,若response包含新的url,再返回新的requests请求存入调度中进行爬取,直到解析出所有的item所需的数据之后return给管道处理。
- 安装scrapy
$ pip install scrapy
- 创建scrapy项目
$ scrapy startproject scrapyProject
- 生成爬虫
$ scrapy genspider spider_name
- scrapy官方文档
/
- 编写允许爬取的网站域名和起始的url
name = 'shopify'# allowed_domains = ['shopify.com']# 当起始URL比较多的时候,我们采用start_requests方法start_urls = []def start_requests(self):with open('doc/url.txt') as f:for line in f.readlines():# Python strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。# 注意只能去掉首尾base_url = line.strip()# 产品的API接口网址如下url = base_url + 'collections/all/products.json'yield Request(url=url, callback=self.parse, meta={'base_url': base_url})# note:如果要处理的是post请求,可以使用scrapy.FormRequest# def start_requests(self):# return [scrapy.FormRequest("",# formdata={'user': 'john', 'pass': 'secret'},# callback=self.logged_in)]# def logged_in(self, response):# # here you would extract links to follow and return Requests for# # each of them, with another callback# pass
def parse(self, response):# 获取json格式data = json.loads(response.text)products = data.get('products')for product in products:# 使用自定义Item类来存储所需要的数据item = ShopifyItem()item['title'] = product['title']item['image'] = product.get('images')[0].get('src')# Request中可以通过meta传递参数,在返回的response中可通过response.meta['key']获取item['link'] = response.meta['base_url'] + 'products/' + product['handle']item['price'] = product['variants'][0].get('price')yield Request(url=item['link'] + '.json', callback=self.parse_detail,meta={'item': copy.deepcopy(item)})
-
回调函数callback
对爬取内容中的url进行进一步爬取并做数据解析,需要自动接受一个response
-
meta参数
meta是一个字典,主要用于解析函数之间传递值;
请求的元数据,可以通过response中的mata参数获取其中的数据
-
这里传递的item为什么使用深拷贝?
因为scrapy是异步处理框架,如果浅拷贝只是使用了item的引用的话,爬虫异步解析所得的数据可能会重复和混乱,所以这里采用深拷贝,使得各个传递的item之间相互不影响.
-
定义item类的好处
简单明了的说明了自己想要爬取的数据结构类型,而不用手动传递字典
item类的使用
# shopifyProject/items.py
class ShopifyItem(scrapy.Item):# 设置要爬取的信息字段title = scrapy.Field() # 商品名称image = scrapy.Field() # 商品图片地址link = scrapy.Field() # 商品详情页链接price = scrapy.Field() # 商品价格# 针对不同尺寸价格sku不同、价格不同、库存不同sizes = scrapy.Field() # 商品尺码信息: sku,stock,price - {'S': {'sku': 'ccc', 'stock':'', 'price': 100}, 'M':{}}stocks = scrapy.Field() # 商品总库存
pipelines类的使用
class ShopifyprojectPipeline(object):def open_spider(self, spider):passdef process_item(self, item, spider):passreturn itemdef close_spider(self, spider):pass
-
管道类一定要重写process_item函数,另外两个可以按照需求来
-
如果需要使用管道,一定要在配置文件中开启管道功能
ITEM_PIPELINES = {'shopifyProject.pipelines.ShopifyprojectPipeline': 300,'shopifyProject.pipelines.MyImagesPipeline': 1,
}
- 其中MyImagesPipeline为自定义的图片处理的管道
# 继承图片管道的类,在重写其中的图片处理方法
class MyImagesPipeline(ImagesPipeline):def get_media_requests(self, item, info):image_url = item['image']yield scrapy.Request(image_url)def item_completed(self, results, item, info):return item
-
配置文件中管道后面的数字表示优先级,数字越小优先级越高
-
管道处理完之后一定要将item 返回 return item
-
为什么要return item ?
原因在于处理这个item的管道可能并不只有一个,return出去之后交给其他管道处理
项目地址
https://hugeblackdog@gitee.com/hugeblackdog/shopifyProject
scrapy框架的简单理解
scrapy框架的简单应用
-
什么是scrapy?
Scrapy是适用于Python的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。
-
scrapy的基本框架
- 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(下载中间件):一个可以自定义扩展下载功能的组件。
- Spider Middlewares(Spider中间件):一个可以自定扩展和操作引擎和Spider中间通信的功能组件。
流程简述:
引擎打开一个域名之后,找到处理这个网站的爬虫,获取start_urls,然后将请求将这些url交给调度器,调度器以requests返回给引擎,引擎再交给下载器下载页面数据,返回response给引擎,引擎将response交给相应的爬虫处理,提取item所需要的数据,若response包含新的url,再返回新的requests请求存入调度中进行爬取,直到解析出所有的item所需的数据之后return给管道处理。
- 安装scrapy
$ pip install scrapy
- 创建scrapy项目
$ scrapy startproject scrapyProject
- 生成爬虫
$ scrapy genspider spider_name
- scrapy官方文档
/
- 编写允许爬取的网站域名和起始的url
name = 'shopify'# allowed_domains = ['shopify.com']# 当起始URL比较多的时候,我们采用start_requests方法start_urls = []def start_requests(self):with open('doc/url.txt') as f:for line in f.readlines():# Python strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。# 注意只能去掉首尾base_url = line.strip()# 产品的API接口网址如下url = base_url + 'collections/all/products.json'yield Request(url=url, callback=self.parse, meta={'base_url': base_url})# note:如果要处理的是post请求,可以使用scrapy.FormRequest# def start_requests(self):# return [scrapy.FormRequest("",# formdata={'user': 'john', 'pass': 'secret'},# callback=self.logged_in)]# def logged_in(self, response):# # here you would extract links to follow and return Requests for# # each of them, with another callback# pass
def parse(self, response):# 获取json格式data = json.loads(response.text)products = data.get('products')for product in products:# 使用自定义Item类来存储所需要的数据item = ShopifyItem()item['title'] = product['title']item['image'] = product.get('images')[0].get('src')# Request中可以通过meta传递参数,在返回的response中可通过response.meta['key']获取item['link'] = response.meta['base_url'] + 'products/' + product['handle']item['price'] = product['variants'][0].get('price')yield Request(url=item['link'] + '.json', callback=self.parse_detail,meta={'item': copy.deepcopy(item)})
-
回调函数callback
对爬取内容中的url进行进一步爬取并做数据解析,需要自动接受一个response
-
meta参数
meta是一个字典,主要用于解析函数之间传递值;
请求的元数据,可以通过response中的mata参数获取其中的数据
-
这里传递的item为什么使用深拷贝?
因为scrapy是异步处理框架,如果浅拷贝只是使用了item的引用的话,爬虫异步解析所得的数据可能会重复和混乱,所以这里采用深拷贝,使得各个传递的item之间相互不影响.
-
定义item类的好处
简单明了的说明了自己想要爬取的数据结构类型,而不用手动传递字典
item类的使用
# shopifyProject/items.py
class ShopifyItem(scrapy.Item):# 设置要爬取的信息字段title = scrapy.Field() # 商品名称image = scrapy.Field() # 商品图片地址link = scrapy.Field() # 商品详情页链接price = scrapy.Field() # 商品价格# 针对不同尺寸价格sku不同、价格不同、库存不同sizes = scrapy.Field() # 商品尺码信息: sku,stock,price - {'S': {'sku': 'ccc', 'stock':'', 'price': 100}, 'M':{}}stocks = scrapy.Field() # 商品总库存
pipelines类的使用
class ShopifyprojectPipeline(object):def open_spider(self, spider):passdef process_item(self, item, spider):passreturn itemdef close_spider(self, spider):pass
-
管道类一定要重写process_item函数,另外两个可以按照需求来
-
如果需要使用管道,一定要在配置文件中开启管道功能
ITEM_PIPELINES = {'shopifyProject.pipelines.ShopifyprojectPipeline': 300,'shopifyProject.pipelines.MyImagesPipeline': 1,
}
- 其中MyImagesPipeline为自定义的图片处理的管道
# 继承图片管道的类,在重写其中的图片处理方法
class MyImagesPipeline(ImagesPipeline):def get_media_requests(self, item, info):image_url = item['image']yield scrapy.Request(image_url)def item_completed(self, results, item, info):return item
-
配置文件中管道后面的数字表示优先级,数字越小优先级越高
-
管道处理完之后一定要将item 返回 return item
-
为什么要return item ?
原因在于处理这个item的管道可能并不只有一个,return出去之后交给其他管道处理
项目地址
https://hugeblackdog@gitee.com/hugeblackdog/shopifyProject