scrapy框架的簡介與使用
Scrapy框架
-
-
crapy Engine(引擎): 負責Spider、ItemPipeline、Downloader、Scheduler中間的通訊,訊號、資料傳遞等。
-
Scheduler(排程器): 它負責接受引擎傳送過來的Request請求,並按照一定的方式進行整理排列,入隊,當引擎需要時,交還給引擎。
-
Downloader(下載器):負責下載Scrapy Engine(引擎)傳送的所有Requests請求,並將其獲取到的Responses交還給Scrapy Engine(引擎),由引擎交給Spider來處理,
-
Spider(爬蟲):它負責處理所有Responses,從中分析提取資料,獲取Item欄位需要的資料,並將需要跟進的URL提交給引擎,再次進入Scheduler(排程器),
-
Item Pipeline(管道):它負責處理Spider中獲取到的Item,並進行進行後期處理(詳細分析、過濾、儲存等)的地方.
-
Downloader Middlewares(下載中介軟體):你可以當作是一個可以自定義擴充套件下載功能的元件。
-
Spider Middlewares(Spider中介軟體):你可以理解為是一個可以自定擴充套件和操作引擎和Spider中間通訊的功能元件(比如進入Spider的Responses;和從Spider出去的Requests)
-
Scrapy框架的使用
-
建立一個scrapy專案
- scrapy startproject 專案名
-
scrapy genspider 爬蟲名 域名
- scrapy startproject 專案名
-
執行爬蟲專案
- scrapy crawl 爬蟲名
- 建立完爬蟲專案後會自動生成以下程式碼
-
import scrapy class TestSpider(scrapy.Spider): # 爬蟲名稱 name = 'test' # 設定允許爬取的域(可以指定多個) allowed_domains = ['baidu.com'] # 設定起始url(設定多個) start_urls = ['http://baidu.com/'] def parse(self, response): ''' 是一個回撥方法,起始url請求成功後,會回撥這個方法 :param response: 響應結果 :return: ''' pass
-
在parse中自定義解析方式
-
def parse(self, response): ''' 在parse回撥方法中 step1;提取目標資料 step2;獲取新的url :param response: 請求的響應結果 :return: ''' print(response.status) #response.xpath(): 使用xpath語法,得到的是selectorlist物件 # response.css(): 使用css選擇器,得到的是selectorlist物件 # extract(): 將selector 序列化為unicode字串 # step1;提取目標資料 # 獲取分類列表 tags = response.xpath('//div[@class="Taright"]/a') # tags = response.css('.Taright a') for tag in tags: # 例項化一個item,用來儲存資料 tag_item = ChinazspidertagItem() # 獲取網站分類的名稱 # tagname = tag.xpath('./text()')[0].extract() tagname = tag.xpath('./text()').extract_first('') tag_item['tagname'] = tagname # 使用css取值(文字) # tagname = tag.css('::text').extract_first('') # 獲取網站分類的首頁url地址 # first_url = tag.xpath('./@href')[0].extract() first_url = tag.xpath('./@href').extract_first('') tag_item['firsturl'] = first_url # css取值(屬性) # first_url = tag.css('::attr(href)').extract_first('') print(tag_item) # print(type(tagname),type(first_url)) # print(tagname,first_url) # 將獲取到的資料交給管道處理 yield tag_item # http://top.chinaz.com/hangye/index_yule_yinyue.html # http://top.chinaz.com/hangye/index_yule_yinyue_2.html ''' url,設定需要發起請求的url地址 callback=None,設定請求成功後的回撥方法 method='GET',請求方式,預設為get請求 headers=None,設定請求頭,字典型別 cookies=None,設定cookies資訊,模擬登入使用者,字典型別 meta=None,傳遞引數(字典型別) encoding='utf-8',設定編碼 dont_filter=False, 是否去重,預設為false,表示去重 errback=None, 設定請求失敗後的回撥 ''' yield scrapy.Request(first_url,callback=self.parse_tags_page)
-
-
關於yeild函式介紹
-
簡單地講,yield 的作用就是把一個函式變成一個 generator(生成器),帶有 yield 的函式不再是一個普通函式,Python 直譯器會將其視為一個 generator,帶有yeild的函式遇到yeild的時候就返回一個迭代值,下次迭代時, 程式碼從 yield 的下一條語句繼續執行,而函式的本地變數看起來和上次中斷執行前是完全一樣的,於是函式繼續執行, 直到再次遇到 yield。
-
通俗的講就是:在一個函式中,程式執行到yield語句的時候,程式暫停,返回yield後面表示式的值,在下一次呼叫的時候,從yield語句暫停的地方繼續執行,如此迴圈,直到函式執行完。
Item pipeline(管道檔案)使用
- 當Item在Spider中被收集之後,它將會被傳遞到Item Pipeline,這些Item Pipeline元件按定義的順序處理Item。
-
-
爬蟲資料持久化
- 將資料存入mysql資料庫
-
ITEM_PIPELINES = {
'douban.pipelines.DoubanPipeline': 300,
}關於資料庫的相關配置
MYSQL_HOST = '127.0.0.1'
MYSQL_PORT = 3306
MYSQL_USER = ''
MYSQL_PWD = ''
MYSQL_DB = ''
pipelines.py管道檔案 -
往資料庫裡插資料 class ChinazspiderPipeline(object): def __init__(self): ''' 初始化方法 ''' # self.file = open('chinaz.json','a') # 建立資料庫連結 self.client = pymysql.Connect( '127.0.0.1', 'root', 'czj1234', 'chinaz', 3306, charset='utf8' ) # 建立遊標 self.cursor = self.client.cursor() def open_spider(self, spider): ''' 爬蟲啟動的時候回撥用一次 :param spider: :return: ''' print('爬蟲開啟') pass def process_item(self, item, spider): ''' 這個方法必須實現,爬蟲檔案中所有的item 都會經過這個方法 :param item: 爬蟲檔案傳遞過來的item物件 :param spider: 爬蟲檔案例項化的物件 :return: ''' # 儲存到本地json檔案 data_dict = dict(item) # import json # json_data = json.dumps(data_dict,ensure_ascii=False) # self.file.write(json_data+'\n') # 使用isisinstance判斷item要儲存的表 # if isinstance(item,ChinazprojectWebInfoItem): # print('網站資訊') # tablename = 'webinfo' # elif isinstance(item,ChinazspidertagItem): # print('網站分類資訊') # tablename = 'tags' # # # # 往資料庫裡寫 # sql = """ # insert into %s(%s) # values (%s) # """ % (tablename,','.join(data_dict.keys()), ','.join(['%s'] * len(data_dict))) sql,data = item.get_insert_sql_data(data_dict) try: self.cursor.execute(sql, list(data_dict.values())) self.client.commit() except Exception as err: self.client.rollback() print(err) # 如果有多個管道檔案,一定要return item , 否則下一管道無法接收到item print('經過了管道') return item def close_spider(self, spider): ''' 爬蟲結束的時候呼叫一次 :param spider: :return: ''' # self.file.close() self.client.close() self.cursor.close() print('爬蟲結束')