Scrapy Shell
Scrapy提供了一个shell,用来方便的测试规则。当然也不仅仅局限于这一个功能。
打开Scrapy Shell
开cmd终端,进入到Scrapy项目所在的目录,然后进入到scrapy框架所在的虚拟环境中,输入命令scrapy shell [链接]。就会进入到scrapy的shell环境中。在这个环境中,你可以跟在爬虫的parse方法中一样使用了。
Request对象
Request对象在我们写爬虫,爬取一页的数据需要重新发送一个请求的时候调用。这个类需要传递一些参数,其中比较常用的参数有:
- url:这个request对象发送请求的url。
- callback:在下载器下载完相应的数据后执行的回调函数。
- method:请求的方法。默认为GET方法,可以设置为其他方法。
- headers:请求头,对于一些固定的设置,放在settings.py中指定就可以了。对于那些非固定的,可以在发送请求的时候指定。
- meta:比较常用。用于在不同的请求之间传递数据用的。
- encoding:编码。默认的为utf-8,使用默认的就可以了。
- dont_filter:表示不由调度器过滤。在执行多次重复的请求的时候用得比较多。
- errback:在发生错误的时候执行的函数。
Response对象
Response对象一般是由Scrapy给你自动构建的。因此开发者不需要关心如何创建Response对象,而是如何使用他。Response对象有很多属性,可以用来提取数据的。主要有以下属性:
- meta:从其他请求传过来的meta属性,可以用来保持多个请求之间的数据连接。
- encoding:返回当前字符串编码和解码的格式。
- text:将返回来的数据作为unicode字符串返回。
- body:将返回来的数据作为bytes字符串返回。
- xpath:xapth选择器。
- css:css选择器。
发送POST请求:
在请求数据的时候发送post请求:
- 如果想在爬虫一开始的时候就发送post请求,那么应该重写
start_requests
方法。在这个方法中,发送post请求。 - 或者在parse中使用scrapy.FormRequest.from_response()来发送请求。这是先执行了原来的start_request方法,即先GET请求start_urls中的链接,返回来的响应在POST请求。
# -*- coding: utf-8 -*-
import scrapy
class RenrenspiderSpider(scrapy.Spider):
name = 'renrenspider'
allowed_domains = ['renren.com']
start_urls = ['http://renren.com/']
# def start_requests(self):
# url = "http://www.renren.com/PLogin.do"
# data = {"email":"","password":""}
# request = scrapy.FormRequest(url,formdata=data,callback=self.parse_page)
# yield request
#
# def parse_page(self,response):
# print("登陆")
# request = scrapy.Request(url='http://www.renren.com/880151247/profile',callback=self.parse_profile)
# yield request
#
# def parse_profile(self,response):
# with open('dp.html','w',encoding='utf-8') as fp:
# fp.write(response.text)
def parse(self, response):
data = {"email":"","password":""}
yield scrapy.FormRequest.from_response(response,formdata=data,callback=self.parse_page)
def parse_page(self,response):
print("登陆")
request = scrapy.Request(url='http://www.renren.com/880151247/profile',callback=self.parse_profile)
yield request
def parse_profile(self,response):
with open('dp.html','w',encoding='utf-8') as fp:
fp.write(response.text)
下载文件和图片
Scrapy为下载item中包含的文件(比如在爬取到产品时,同时也想保存对应的图片)提供了一个可重用的item pipelines。这些pipeline有些共同的方法和结构(我们称之为media pipeline)。一般来说你会使用Files Pipeline或者Images Pipeline。
使用内置的下载文件的方法优点:
- 避免重新下载最近已经下载过的文件。
- 可以方便的指定文件存储的路径。
- 可以将下载的图片转换成通用的格式。比如png或jpg。
- 可以方便的生成缩略图。
- 可以方便的检测图片的宽和高,确保他们满足最小限制。
- 异步下载,效率非常高。
下载文件的Files Pipeline:
当使用Files Pipeline下载文件的时候,按照以下步骤来完成:
- 定义好一个Item,然后在这个item中定义两个属性,分别为file_urls以及files。file_urls是用来存储需要下载的文件的url链接,需要给一个列表。
- 当文件下载完成后,会把文件下载的相关信息存储到item的files属性中。比如下载路径、下载的url和文件的校验码等。
- 在配置文件settings.py中配置FILES_STORE,这个配置是用来设置文件下载下来的路径。
- 启动pipeline:在ITEM_PIPELINES中设置scrapy.pipelines.files.FilesPipeline:1。
下载图片的Images Pipeline:
- 定义好一个Item,然后在这个item中定义两个属性,分别为image_urls以及images。image_urls是用来存储需要下载的图片的url链接,需要给一个列表。
items.py:
import scrapy
class CarimageItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
image_urls = scrapy.Field()
images = scrapy.Field()
- 当文件下载完成后,会把文件下载的相关信息存储到item的images属性中。比如下载路径、下载的url和图片的校验码等。
- 在配置文件settings.py中配置IMAGES_STORE,这个配置是用来设置图片下载下来的路径。
#图片下载路径
IMAGES_STORE = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images')
- 启动pipeline:在ITEM_PIPELINES中设置scrapy.pipelines.images.ImagesPipeline:1
在pipeline.py中的类需要继承ImagesPipeline或者FilesPipeline类。可以重写ImagesPipeline和FilesPipeline中的方法来达到我们的需求
class CarimagesPipeline(ImagesPipeline):
#绑定Items对象
def get_media_requests(self, item, info):
request_objs = super(CarimagesPipeline, self).get_media_requests(item,info)
for request_obj in request_objs:
request_obj.item = item
return request_objs
#重写文件存储路径
def file_path(self, request, response=None, info=None):
path = super(CarimagesPipeline, self).file_path(request,response,info)
cattab_title = request.item.get('cattab_title')
category = request.item.get('category')
images_store = os.path.join(settings.IMAGES_STORE,cattab_title)
category_path = os.path.join(images_store,category)
if not os.path.exists(category_path):
os.makedirs(category_path)
image_name = path.replace("full/","")
image_path = os.path.join(cattab_title+'/'+category+'/',image_name)
return image_path
注:参考网易云知了课堂。