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
注:參考網易雲知了課堂。