數據持久化的兩種方式:(1)基於終端指令的持久化存儲;(2)基於管道的持久化存儲
基於終端指令的持久化存儲
在爬蟲文件的parse方法中必須要return可迭代對象類型(通常為列表或字典等)的返回值,該返回值作為基於終端指令持久化指定文件的輸出內容。
執行輸出指定格式進行存儲-------將爬取到的數據寫入不同格式的文件中進行存儲,存儲格式有限:
scrapy crawl 爬蟲文件 -o xxx.json scrapy crawl 爬蟲文件 -o xxx.xml scrapy crawl 爬蟲文件 -o xxx.csv
基於管道的持久化存儲
(1)編寫爬蟲文件進行數據解析
(2)在items.py中定義相關字段(用於存儲解析的數據)
(3)在爬蟲文件中將解析到的數據封裝在實例化的item對象中
(4)通過yield將item對象提交到pipelines.py中的管道
(5)在管道中進行任意方式的數據持久化(數據庫持久化需要重寫兩個方法open_spider和close_spider)
(6)在settings.py配置文件中開啟管道(ITEM_PIPELINES ,同時處理ROBOTSTXT_OBEY協議、USER_AGENT 偽裝和LOG_LEVEL='ERROR'日志輸出等級)
(7)啟動爬蟲:scrapy crawl 爬蟲文件
百度首頁超鏈接數據解析與持久化存儲
1.編寫爬蟲文件firstPro.py

1 # -*- coding: utf-8 -*- 2 import scrapy 3 from firstPro.items import FirstproItem 4 5 6 class FirstbaiduSpider(scrapy.Spider): 7 name = 'firstBaidu' # 爬蟲文件(應用)名 8 # allowed_domains = ['https://www.baidu.com/']#域名限定,一般直接注釋 9 start_urls = ['https://www.baidu.com//'] # 起始url,創建應用時指定的,可修改 10 11 def parse(self, response): # 自動訪問起始URL並獲取結果后的回調函數,參數respons為起始請求的響應對象,可以直接調用封裝好的xpath解析 12 13 # print(response.text)#獲取字符串類型的響應內容 14 # print(response.body)#獲取字節類型的相應內容 15 16 # 進行數據解析 17 a_list = response.xpath('//p[@id="nv"]/a') # 注意頁面解析標簽定位!!!瀏覽器看到的標簽位置和實際爬去的頁面內容位置可能不一樣 18 for a in a_list: 19 # scrapy自帶xpath解析獲取文本或屬性需要使用extract()或extract_first() 20 title = a.xpath('./text()').extract_first().replace('\xa0','') # extract_first()從結果列表獲取第一個值 21 url = a.xpath('./@href')[0].extract() # extract()從解析結果中取出所有制,結果只有一個就是字符串,多個就是列表 22 # print(title, url) 23 24 # 解析后的數據需要進行持久化存儲: 25 # (1)items.py中定義相關存儲字段; 26 item = FirstproItem() 27 # (2)實例化item對象將解析的數據進行封裝; 28 item['title'] = title 29 item['url'] = url 30 # (3)使用yield將item對象提交給管道處理 31 yield item 32 33 pass
2.自定義items.py中的類字段

1 # -*- coding: utf-8 -*- 2 3 # Define here the models for your scraped items 4 # 5 # See documentation in: 6 # https://docs.scrapy.org/en/latest/topics/items.html 7 8 import scrapy 9 10 11 class FirstproItem(scrapy.Item): 12 # define the fields for your item here like: 13 # name = scrapy.Field() 14 title=scrapy.Field()#存儲標題 15 url=scrapy.Field()#存儲連接 16 pass
3.管道pipilines.py處理類定義
注意:
(1)要想使用管道進行數據持久化,必須在settings.py中進行開啟配置;
(2)可以定義多個管道類進行處理,但是在每個process_item函數中必須return item 傳遞給其它管道使用;
(3)process_item參數item只接受爬蟲文件提交來的item對象,參數spider是爬蟲文件中類的實例化對象,可以進行數據傳遞;
(4)如果要對數九持久化寫入到數據庫,需要在管道類中重寫open_spider和close_spider方法,這兩個方法只會被執行一次;
(5)對於圖片類(視頻、音頻等二進制)數據的下載有可以定義新的管道繼承相關類既可以直接實現圖片的下載,注意要在settings.py中指定存儲路徑IMAGES_STORE=path

1 # 注意: 2 # (1)要想使用管道進行數據持久化,必須在settings.py中進行開啟配置 3 # (2)可以定義多個管道類進行處理,但是在每個process_item函數中必須return item 傳遞給其它管道使用 4 # (3)process_item參數item只接受爬蟲文件提交來的item對象,參數spider是爬蟲文件中類的實例化對象,可以進行數據傳遞; 5 # (4)如果要對數九持久化寫入到數據庫,需要在管道類中重寫open_spider和close_spider方法,這兩個方法只會被執行一次; 6 # (5)對於圖片類(視頻、音頻等二進制)數據的下載有可以定義新的管道繼承相關類既可以直接實現圖片的下載 7 8 # 默認管道處理 9 class FirstproPipeline(object): 10 # item對象處理函數 11 def process_item(self, item, spider): 12 print(item) 13 return item

1 # (1)自定義的文件持久化管道 2 class TofilePipeline(object): 3 # 構造方法初始化一個屬性文件句柄,也可以定義一個類變量:fp=None 4 def __init__(self): 5 self.fp = None 6 7 # 打開文件句柄 8 def open_spider(self, spider): 9 print('開始寫入數據...') 10 self.fp = open('a.text', 'w', encoding='utf-8') 11 12 # 關閉文件進行系統資源回收 13 def close_spider(self, spider): 14 self.fp.close() 15 print('數據下載成功,爬蟲結束!') 16 17 def process_item(self, item, spider): 18 self.fp.write(f'{item["title"]}:{item["url"]}\n') 19 return item

1 # (2)自定義的基於mysql數據庫持久化管道 2 import pymysql 3 class ToMysqlPipeline(object): 4 conn = None 5 cursor = None 6 7 # 建立數據庫連接 8 def open_spider(self, spider): 9 print('建立數據庫連接...') 10 self.conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='123456', db='spider') 11 12 # 關閉數據庫連接 13 def close_spider(self, spider): 14 self.cursor.close() # conn斷開時也會自動斷開 15 self.conn.close() 16 print('成功寫入數據庫!') 17 18 def process_item(self, item, spider): 19 sql = f'insert into table1 values ({item["title"]},{item["url"]})' 20 self.cursor = self.conn.cursor() 21 22 # 數據庫事務操作 23 try: 24 self.cursor.execute(sql) 25 self.conn.commit() 26 except Exception as e: 27 print(e) 28 self.conn.rollback() 29 30 return item

1 # (3)自定義的基於redis數據庫持久化管道 2 import redis 3 class ToRedisPipeline(object): 4 conn = None 5 6 # 建立數據庫連接 7 def open_spider(self, spider): 8 print('建立數據庫連接...') 9 self.conn = redis.Redis(host='127.0.0.1', port=6379) 10 11 def process_item(self, item, spider): 12 self.conn.lpush('data', dict(item)) # 將item對象以字典形式存儲在redis列表結構中 13 return item

1 # (4)自定義的基於mongodb數據庫持久化管道 2 import pymongo 3 class ToMongoDBPipeline(object): 4 conn = None 5 6 # 建立數據庫連接 7 def open_spider(self, spider): 8 print('建立數據庫連接...') 9 self.conn = pymongo.MongoClient(host='127.0.0.1', port=27017) 10 11 # 關閉數據庫連接(可以不寫) 12 def close_spider(self, spider): 13 self.conn.close() 14 print('成功寫入數據庫!') 15 16 def process_item(self, item, spider): 17 self.conn.Spider.col.insert_one({item["title"]:item["url"]}) #將title:url存入mongodb的Spider數據庫中col集合(表)中 18 return item

1 # (5)自定義圖片等文件的下載管道 2 #IMAGES_STORE='filepath'在settings設置文件中指定存儲圖片的下載路徑 3 import os 4 import scrapy 5 from scrapy.pipelines.images import ImagesPipeline 6 7 class ImageDownloadPipeline(ImagesPipeline): 8 #接收item且將item中存儲的url進行請求發送 9 def get_media_requests(self, item, info): # 下載圖片 10 url=item["url"] 11 yield scrapy.Request(url, meta={'item': item}) 12 13 # 指定下載路徑 14 def file_path(self, request, response=None, info=None): 15 item = request.meta['item'] 16 img_name = request.url.split('/')[-1] 17 path='圖片'#自動會創建文件夾,同時存放在settings.py中指定的IMAGES_STORE配置路徑下 18 filename = os.path.join(path, img_name) 19 print(f'正在下載------{filename}...') 20 return filename 21 22 # 將item傳遞給下一個即將被執行的管道類 23 def item_completed(self, result, item, info): 24 return item
4.settings.py配置文件
1 # Crawl responsibly by identifying yourself (and your website) on the user-agent 2 # USER_AGENT = 'firstPro (+http://www.yourdomain.com)' 3 # (1)UA偽造 4 USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36' 5 6 # Obey robots.txt rules 7 # ROBOTSTXT_OBEY = True 8 # (2)不遵守robots協議 9 ROBOTSTXT_OBEY = False 10 11 # (3)設置日志輸出等級 12 LOG_LEVEL = 'ERROR' 13 14 15 16 17 # Configure item pipelines 18 # See https://docs.scrapy.org/en/latest/topics/item-pipeline.html 19 # 取消注釋,開啟管道,數字代表優先級,越小級別越高,按需要開啟 20 ITEM_PIPELINES = { 21 'firstPro.pipelines.FirstproPipeline': 300, 22 'firstPro.pipelines.TofilePipeline': 200, 23 # 'firstPro.pipelines.ToMysqlPipeline': 600, 24 'firstPro.pipelines.ToRedisPipeline': 100, 25 # 'firstPro.pipelines.ToMongoDBPipeline': 400, 26 # 'firstPro.pipelines.ImageDownloadPipeline': 200, 27 } 28 29 #如果開啟圖片下載管道,需要指定下載目錄 30 # IMAGES_STORE='./images'
5.啟動爬蟲程序
scrapy crawl firstPro