Scrapy實戰篇(六)之爬取360圖片數據和圖片


  

  本篇文章我們以360圖片為例,介紹scrapy框架的使用以及圖片數據的下載。

 

  目標網站:http://images.so.com/z?ch=photography

  思路:分析目標網站為ajax加載方式,通過構造目標url從而請求數據,將圖片數據存儲在本地,將圖片的屬性存儲在mongodb中。

 

  1、首先定義我們需要抓取的字段

class ImageItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    collection = 'images'  #代表mongodb的的集合名稱
    #下面四個字段分別是圖片id,鏈接,標題,縮率圖
    id = Field()
    url = Field()
    title = Field()
    thumb = Field()

 

  

  2、構造我們要爬取的url;由於目標網站時ajax加載的,展示的數據在http://images.so.com/zj?ch=photography&sn=30&listtype=new&temp=1中以json的形式存儲,不斷的下拉頁面之后,每次變化的參數只有sn,並且每次以30的增量增加,第一頁sn=30,第二頁為60,則sn和頁碼的關系為sn*30,所以我們可以構造出url

 

#定義起始需要爬取的url列表,首先從spider中發送給調度引擎
    def start_requests(self):
        data = {'ch':'photography','listtype':'new','temp':1}
        base_url = 'http://images.so.com/zj?'
        for page in range(1,self.settings.get('MAX_PAGE') + 1):   #MAX_PAGE以參數的形式在settings文件中配置
            data['sn'] = page * 30
            url = base_url + urlencode(data)
            yield Request(url,self.parse)

 

 

  3、編寫解析函數,返回的數據是json格式

#解析函數
    def parse(self, response):
        result = json.loads(response.text)   #將JSON文本字符串轉為JSON對象
        for image in result.get('list'):
            item = ImageItem()
            item['id'] = image.get('imageid')
            item['url'] = image.get('qhimg_url')
            item['title'] = image.get('group_title')
            item['thumb'] = image.get('qhimg_thumb_url')
            yield item

 

 

  4、編寫pipeline文件,將圖片屬性數據存入mongo,將圖片存儲到本地

import pymongofrom scrapy import Request
from scrapy.exceptions import DropItem
from scrapy.pipelines.images import ImagesPipeline


#定義了兩個個Pipeline,分別為數據存儲到mongodb,圖片下載到本地
#在settings中定義Pipeline的執行順序
class MongoPipeline(object):
    def __init__(self,mongo_url,mongo_db):
        self.mongo_url = mongo_url
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls,crawler):
        return cls(
            mongo_url=crawler.settings.get('MONGO_URL'),
            mongo_db=crawler.settings.get('MONGO_DB')
        )

    def open_spider(self,spider):
        self.client = pymongo.MongoClient(self.mongo_url)
        self.db = self.client[self.mongo_db]

    def process_item(self, item, spider):
        self.db[item.collection].insert(dict(item))
        return item

    def close(self,spider):
        self.client.close()

class ImagesPipeline(ImagesPipeline): def file_path(self,request,response=None,info=None): url = request.url file_name = url.split('/')[-1] return file_name def item_completed(self,results,item,info): image_paths=[x['path'] for ok,x in results if ok] if not image_paths: raise DropItem('Image Download Failed') return item def get_media_requests(self,item,info): yield Request(item['url'])

 

第一個為MongoPipeline,通過類方法from_crawler從settings文件中獲取mongodb的配置信息,將蜘蛛文件中返回的item存入mongo數據庫。

 

第二個為ImagesPipeline,scrapy提供了專門處理下載的Pipeline,包括文件下載和圖片下載,下載過程支持異步和多線程,效率極高。

 

首先定義存儲文件的路徑,需要定義一個IMAGES_STORE變量,在settings文件中添加一行

IMAGES_STORE = './images

 

我們將路徑定義在當前路徑下的images中,即下載的圖片都會存儲在這個文件夾中。

 

  內置的ImagesPipeline會默認讀取Item對象的image_urls字段,並認為該變量是一個列表,會遍歷這個字段,然后取出url進行圖片下載。

  但是我們上面定義的模型可以看出,Item對象的圖片連接並不是image_url,也不是列表形式的,而是單個url,所以為了實現下載,需要重寫ImagePipeline,繼承內置的ImagePileline,再次我們重寫了三個方法,分別是

  1)get_media_requests():它的第一個參數item就是爬取生成的Item對象,我們將它的url取出來,直接生成Request對象返回,從而加入調度隊列,等待被調度,執行下載。

  2)file_path():它的第一個參數request就是當前下載的Request對象,這個方法用來返回保存的文件名稱,直接將圖片鏈接的最后一部分當做文件名稱即可。

  3)item_completed():它是當單個Item完成下載時的處理方法,因為並不是每張圖片都會下載成功,所以需要分析下載結果並剔除下載失敗的圖片,該方法的第一個參數results就是該item對象的下載結果,它是一個列表的形式,列表的每一個元素都是一個元組,其中包含了下載成功或者失敗的信息。

 

  5、在settings中激活pipeline,並配置需要的配置項

ITEM_PIPELINES = {
   'images360.pipelines.ImagesPipeline': 300,
   'images360.pipelines.MongoPipeline': 301,
}

 

 

  6、執行爬蟲,獲取數據即可。

  scrapy crawl  images

 

  項目完整代碼:https://gitee.com/liangxinbin/Scrpay/tree/master/images360


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM