imagespipeline是scrapy自帶的類,用來處理圖檔(爬取時将圖檔下載下傳到本地)用的。
優勢:
将下載下傳圖檔轉換成通用的jpg和rgb格式
避免重複下載下傳
縮略圖生成
圖檔大小過濾
異步下載下傳
......
工作流程:
爬取一個item,将圖檔的urls放入image_urls字段
從spider傳回的item,傳遞到item pipeline
當item傳遞到imagepipeline,将調用scrapy 排程器和下載下傳器完成image_urls中的url的排程和下載下傳。
圖檔下載下傳成功結束後,圖檔下載下傳路徑、url和校驗和等資訊會被填充到images字段中。
實作方式:
自定義pipeline,優勢在于可以重寫imagepipeline類中的實作方法,可以根據情況對照片進行分類;
直接使用imagepipeline類,簡單但不夠靈活;所有的圖檔都是儲存在full檔案夾下,不能進行分類
實踐:爬取http://699pic.com/image/1/這個網頁下的前四個圖檔集(好進行分類示範)
這裡使用方法一進行實作:
步驟一:建立項目與爬蟲
1.建立工程:scrapy startproject xxx(工程名)
2.建立爬蟲:進去到上一步建立的目錄下:scrapy genspider xxx(爬蟲名) xxx(域名)
步驟二:建立start.py
1 from scrapy import cmdline
2
3 cmdline.execute("scrapy crawl 699pic(爬蟲名)".split(" "))
步驟三:設定settings
1.關閉機器人協定,改成false
2.設定headers
3.打開item_pipelines
将項目自動生成的pipelines注釋掉,黃色部分是下面步驟中自己寫的pipeline,這裡先不寫。
步驟四:item
1 class img699picitem(scrapy.item):
2 # 分類的标題
3 category=scrapy.field()
4 # 存放圖檔位址
5 image_urls=scrapy.field()
6 # 下載下傳成功後傳回有關images的一些相關資訊
7 images=scrapy.field()
步驟五:寫spider
import scrapy
from ..items import img699picitem
import requests
from lxml import etree
class a699picspider(scrapy.spider):
name = '699pic'
allowed_domains = ['699pic.com']
start_urls = ['http://699pic.com/image/1/']
headers={
'user-agent':'mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko) chrome/67.0.3396.62 safari/537.36'
}
def parse(self, response):
divs=response.xpath("//div[@class='special-list clearfix']/div")[0:4]
for div in divs:
category=div.xpath("./a[@class='special-list-title']//text()").get().strip()
url=div.xpath("./a[@class='special-list-title']/@href").get().strip()
image_urls=self.parse_url(url)
item=img699picitem(category=category,image_urls=image_urls)
yield item
def parse_url(self,url):
response=requests.get(url=url,headers=self.headers)
htmlelement=etree.html(response.text)
image_urls=htmlelement.xpath("//div[@class='imgshow clearfix']//div[@class='list']/a/img/@src")
return image_urls
步驟六:pipelines
import os
from scrapy.pipelines.images import imagespipeline
from . import settings
class img699picpipeline(object):
def process_item(self, item, spider):
return item
class images699pipeline(imagespipeline):
def get_media_requests(self, item, info):
# 這個方法是在發送下載下傳請求之前調用的,其實這個方法本身就是去發送下載下傳請求的
request_objs=super(images699pipeline, 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(images699pipeline, self).file_path(request,response,info)
category=request.item.get('category')
image_store=settings.images_store
category_path=os.path.join(image_store,category)
if not os.path.exists(category_path):
os.makedirs(category_path)
image_name=path.replace("full/","")
image_path=os.path.join(category_path,image_name)
return image_path
步驟七:傳回到settings中
1.将黃色部分填上
2.存放圖檔的總路徑
images_store=os.path.join(os.path.dirname(os.path.dirname(__file__)),'images')
最終結果:
如您對本文有疑問或者有任何想說的,請點選進行留言回複,萬千網友為您解惑!