在上两节当中,我们爬取了360图片,但是我们需要将图片下载下来,这将如何下载和存储呢?
下边叙述一下三种情况:1、将图片下载后存储到MongoDB数据库;2、将图片下载后存储在MySQL数据库;3、将图片下载到本地文件
话不多说,直接上代码:
1、通过item定义存储字段
1 # item.py 2 import scrapy 3 4 class Bole_mode(scrapy.Item): 5 collection = "images" # collection为MongoDB储表名名称 6 table = "images" # table为MySQL的存储表名名称 7 id = scrapy.Field() # id 8 url = scrapy.Field() # 图片链接 9 title = scrapy.Field() # 标题 10 thumb = scrapy.Field() # 缩略图
2、配置settings文件获取数据库信息
1 # -*- coding: utf-8 -*- 2 3 # Scrapy settings for bole project 4 # 5 # For simplicity, this file contains only settings considered important or 6 # commonly used. You can find more settings consulting the documentation: 7 # 8 # https://doc.scrapy.org/en/latest/topics/settings.html 9 # https://doc.scrapy.org/en/latest/topics/downloader-middleware.html 10 # https://doc.scrapy.org/en/latest/topics/spider-middleware.html 11 12 BOT_NAME = 'bole' 13 14 SPIDER_MODULES = ['BLZX.spiders'] 15 NEWSPIDER_MODULE = 'BLZX.spiders' 16 17 18 # Crawl responsibly by identifying yourself (and your website) on the user-agent 19 #USER_AGENT = 'bole (+http://www.yourdomain.com)' 20 21 # Obey robots.txt rules 22 ROBOTSTXT_OBEY = False 23 USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.54 Safari/536.5' 24 25 # Configure maximum concurrent requests performed by Scrapy (default: 16) 26 #CONCURRENT_REQUESTS = 32 27 28 # Configure a delay for requests for the same website (default: 0) 29 # See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay 30 # See also autothrottle settings and docs 31 #DOWNLOAD_DELAY = 3 32 # The download delay setting will honor only one of: 33 #CONCURRENT_REQUESTS_PER_DOMAIN = 16 34 #CONCURRENT_REQUESTS_PER_IP = 16 35 36 # Disable cookies (enabled by default) 37 #COOKIES_ENABLED = False 38 39 # Disable Telnet Console (enabled by default) 40 #TELNETCONSOLE_ENABLED = False 41 42 # Override the default request headers: 43 #DEFAULT_REQUEST_HEADERS = { 44 # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 45 # 'Accept-Language': 'en', 46 #} 47 48 # Enable or disable spider middlewares 49 # See https://doc.scrapy.org/en/latest/topics/spider-middleware.html 50 #SPIDER_MIDDLEWARES = { 51 # 'bole.middlewares.BoleSpiderMiddleware': 543, 52 #} 53 54 # Enable or disable downloader middlewares 55 # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html 56 57 58 # DOWNLOADER_MIDDLEWARES = { 59 # 'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware':None, 60 # 'bole.middlewares.ProxyMiddleware':125, 61 # 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware':None 62 # } 63 64 65 66 # Enable or disable extensions 67 # See https://doc.scrapy.org/en/latest/topics/extensions.html 68 #EXTENSIONS = { 69 # 'scrapy.extensions.telnet.TelnetConsole': None, 70 #} 71 72 73 # Configure item pipelines 74 # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html 75 ITEM_PIPELINES = { 76 "bole.pipelines.BoleImagePipeline":2, 77 "bole.pipelines.ImagePipeline":300, 78 "bole.pipelines.MongoPipeline":301, 79 "bole.pipelines.MysqlPipeline":302, 80 } 81 82 83 # Enable and configure the AutoThrottle extension (disabled by default) 84 # See https://doc.scrapy.org/en/latest/topics/autothrottle.html 85 #AUTOTHROTTLE_ENABLED = True 86 # The initial download delay 87 #AUTOTHROTTLE_START_DELAY = 5 88 # The maximum download delay to be set in case of high latencies 89 #AUTOTHROTTLE_MAX_DELAY = 60 90 # The average number of requests Scrapy should be sending in parallel to 91 # each remote server 92 #AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0 93 # Enable showing throttling stats for every response received: 94 #AUTOTHROTTLE_DEBUG = False 95 96 # Enable and configure HTTP caching (disabled by default) 97 # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings 98 #HTTPCACHE_ENABLED = True 99 #HTTPCACHE_EXPIRATION_SECS = 0 100 #HTTPCACHE_DIR = 'httpcache' 101 #HTTPCACHE_IGNORE_HTTP_CODES = [] 102 #HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage' 103 104 105 # 爬取最大页数 106 MAX_PAGE = 50 107 108 # mongodb配置 109 MONGODB_URL = "localhost" 110 MONGODB_DB = "Images360" 111 112 # MySQL配置 113 MYSQL_HOST = "localhost" 114 MYSQL_DATABASE = "images360" 115 MYSQL_PORT = 3306 116 MYSQL_USER = "root" 117 MYSQL_PASSWORD = "123456" 118 119 # 本地配置 120 IMAGES_STORE = r"D:spideroleimage"
3、此处的Middlewares没有做任何修改
1 # -*- coding: utf-8 -*- 2 3 # Define here the models for your spider middleware 4 # 5 # See documentation in: 6 # https://doc.scrapy.org/en/latest/topics/spider-middleware.html 7 8 from scrapy import signals 9 10 11 class BoleSpiderMiddleware(object): 12 # Not all methods need to be defined. If a method is not defined, 13 # scrapy acts as if the spider middleware does not modify the 14 # passed objects. 15 16 @classmethod 17 def from_crawler(cls, crawler): 18 # This method is used by Scrapy to create your spiders. 19 s = cls() 20 crawler.signals.connect(s.spider_opened, signal=signals.spider_opened) 21 return s 22 23 def process_spider_input(self, response, spider): 24 # Called for each response that goes through the spider 25 # middleware and into the spider. 26 27 # Should return None or raise an exception. 28 return None 29 30 def process_spider_output(self, response, result, spider): 31 # Called with the results returned from the Spider, after 32 # it has processed the response. 33 34 # Must return an iterable of Request, dict or Item objects. 35 for i in result: 36 yield i 37 38 def process_spider_exception(self, response, exception, spider): 39 # Called when a spider or process_spider_input() method 40 # (from other spider middleware) raises an exception. 41 42 # Should return either None or an iterable of Response, dict 43 # or Item objects. 44 pass 45 46 def process_start_requests(self, start_requests, spider): 47 # Called with the start requests of the spider, and works 48 # similarly to the process_spider_output() method, except 49 # that it doesn’t have a response associated. 50 51 # Must return only requests (not items). 52 for r in start_requests: 53 yield r 54 55 def spider_opened(self, spider): 56 spider.logger.info('Spider opened: %s' % spider.name) 57 58 59 class BoleDownloaderMiddleware(object): 60 # Not all methods need to be defined. If a method is not defined, 61 # scrapy acts as if the downloader middleware does not modify the 62 # passed objects. 63 64 @classmethod 65 def from_crawler(cls, crawler): 66 # This method is used by Scrapy to create your spiders. 67 s = cls() 68 crawler.signals.connect(s.spider_opened, signal=signals.spider_opened) 69 return s 70 71 def process_request(self, request, spider): 72 # Called for each request that goes through the downloader 73 # middleware. 74 75 # Must either: 76 # - return None: continue processing this request 77 # - or return a Response object 78 # - or return a Request object 79 # - or raise IgnoreRequest: process_exception() methods of 80 # installed downloader middleware will be called 81 return None 82 83 def process_response(self, request, response, spider): 84 # Called with the response returned from the downloader. 85 86 # Must either; 87 # - return a Response object 88 # - return a Request object 89 # - or raise IgnoreRequest 90 return response 91 92 def process_exception(self, request, exception, spider): 93 # Called when a download handler or a process_request() 94 # (from other downloader middleware) raises an exception. 95 96 # Must either: 97 # - return None: continue processing this exception 98 # - return a Response object: stops process_exception() chain 99 # - return a Request object: stops process_exception() chain 100 pass 101 102 def spider_opened(self, spider): 103 spider.logger.info('Spider opened: %s' % spider.name)
4、通过Pipeline对爬取的数据进行存储,分为MongoDB数据库存储,MySQL数据库存储,本地文件夹存储
1 # -*- coding: utf-8 -*- 2 # ==========================MongoDB=========================== 3 import pymongo 4 class MongoPipeline(object): 5 def __init__(self,mongodb_url,mongodb_DB): 6 self.mongodb_url = mongodb_url 7 self.mongodb_DB = mongodb_DB 8 9 @classmethod 10 # 获取settings配置文件当中设置的MONGODB_URL和MONGODB_DB 11 def from_crawler(cls,crawler): 12 return cls( 13 mongodb_url=crawler.settings.get("MONGODB_URL"), 14 mongodb_DB=crawler.settings.get("MONGODB_DB") 15 ) 16 17 # 开启爬虫时连接MongoDB数据库 18 def open_spider(self,spider): 19 self.client = pymongo.MongoClient(self.mongodb_url) 20 self.db = self.client[self.mongodb_DB] 21 22 def process_item(self,item,spider): 23 table_name = item.collection 24 self.db[table_name].insert(dict(item)) 25 return item 26 27 # 关闭爬虫时断开MongoDB数据库连接 28 def close_spider(self,spider): 29 self.client.close() 30 31 32 # ============================MySQL=========================== 33 import pymysql 34 class MysqlPipeline(): 35 def __init__(self,host,database,port,user,password): 36 self.host = host 37 self.database = database 38 self.port = port 39 self.user = user 40 self.password = password 41 42 @classmethod 43 # 获取settings配置文件当中设置的MySQL各个参数 44 def from_crawler(cls,crawler): 45 return cls( 46 host=crawler.settings.get("MYSQL_HOST"), 47 database=crawler.settings.get("MYSQL_DATABASE"), 48 port=crawler.settings.get("MYSQL_PORT"), 49 user=crawler.settings.get("MYSQL_USER"), 50 password=crawler.settings.get("MYSQL_PASSWORD") 51 ) 52 53 # 开启爬虫时连接MongoDB数据库 54 def open_spider(self,spider): 55 self.db = pymysql.connect(host=self.host,database=self.database,user=self.user,password=self.password,port=self.port,charset="utf8") 56 self.cursor = self.db.cursor() 57 58 def process_item(self,item,spider): 59 data = dict(item) 60 keys = ",".join(data.keys()) # 字段名 61 values =",".join(["%s"]*len(data)) # 值 62 sql = "insert into %s(%s) values(%s)"%(item.table, keys, values) 63 self.cursor.execute(sql, tuple(data.values())) 64 self.db.commit() 65 return item 66 67 # 关闭爬虫时断开MongoDB数据库连接 68 def close_spider(self,spider): 69 self.db.close() 70 71 72 73 # # ============================本地=========================== 74 import scrapy 75 from scrapy.exceptions import DropItem 76 from scrapy.pipelines.images import ImagesPipeline 77 78 class ImagePipeline(ImagesPipeline): 79 80 # 由于item里的url不是list,所以重写下面几个函数 81 def file_path(self, request, response=None, info=None): 82 url = request.url 83 file_name = url.split("/")[-1] # 将url连接的最后一部分作为文件名称 84 return file_name 85 86 # results为item对应的图片下载的结果,他是一个list,每个元素为元组,并包含了下载成功和失败的信息 87 def item_completed(self, results, item, info): 88 89 # 获取图片地址path 90 image_paths = [x["path"] for ok,x in results if ok] 91 if not image_paths: 92 raise DropItem("图片下载失败!!") 93 return item 94 95 def get_media_requests(self, item, info): 96 97 # 获取item文件里的url字段并加入队列等待被调用进行下载图片 98 yield scrapy.Request(item["url"])
5、最后就是spider数据爬取了
1 import scrapy 2 import json 3 import sys 4 5 sys.path.append(r'D:spideroleitem.py') 6 from bole.items import Bole_mode 7 8 class BoleSpider(scrapy.Spider): 9 name = 'boleSpider' 10 11 def start_requests(self): 12 url = "https://image.so.com/zj?ch=photography&sn={}&listtype=new&temp=1" 13 page = self.settings.get("MAX_PAGE") 14 for i in range(int(page)+1): 15 yield scrapy.Request(url=url.format(i*30)) 16 17 def parse(self,response): 18 photo_list = json.loads(response.text) 19 item = Bole_mode() 20 for image in photo_list.get("list"): 21 item["id"] = image["id"] 22 item["url"] = image["qhimg_url"] 23 item["title"] = image["group_title"] 24 item["thumb"] = image["qhimg_thumb_url"] 25 yield item
6、最最后就是对爬取的结果展示一下呗(只展示MySQL和本地,MongoDB没打开)
(1) MySQL存储
(2) 本地存储