學習爬蟲之Scrapy框架學習(3)---豆瓣top250電影完整版信息獲取及如何存儲到mysql數據庫;Scrapy shell和Scrapy選擇器;使用到日誌的學習!(nine day)

1.昨天簡單爬取了豆瓣Top250電影的一些信息。今天,咱又來嘗試搞到每個電影的簡介信息。順便看看Scrapy shell和Scrapy選擇器以及scrapy.spider。

(1)第一步:配對成功我們所想要的每個電影的簡介信息:

1.First:觀察網頁可知,我們要想要獲取到每個電影的簡介信息。首先要獲取到每個電影的包含它簡介信息的url。

在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

Second:在爬蟲文件中加入此成功的代碼,並且,我們所獲取到的是request請求,而Scrapy框架裏一切請求都要交給引擎,所以我們要將此request請求yield返回給引擎,讓引擎進行一系列處理。最後,引擎處理完之後,要將處理過後的數據再交給爬蟲文件進行數據解析及獲取,而這就需要我們在爬蟲文件中定義一個專門解析與獲取電影簡介信息的函數(注意:這個函數一定要包含response參數用於接收引擎交給爬蟲文件的數據)

#將下面代碼加到爬蟲文件中parse函數的循環的最下面:
                detail_url=node.xpath('./div/a/@href').extract()[0]
                yield scrapy.Request(detail_url,callback=self.get_detail)
#將下面函數加入爬蟲文件:
    def get_detail(self,response):
        pass

Third:現在,我們就要使用我們自定義的函數get_detail()處理引擎處理過後交給我們的response了。這給咱的是個response,咱繼續分析這個response的網頁源碼,使用xpath匹配到我們所需的電影的簡介信息即可!在這裏插入圖片描述在這裏插入圖片描述

在這裏插入圖片描述將此代碼加入到我們寫的get_detail()函數裏即可:

    def get_detail(self,response):
        #獲取電影簡介信息
        description=response.xpath('//div[@id="link-report"]/span/span[@property="v:summary"]/text()').extract()[0].strip()

注意:我們在進行測試的時候,發現有個電影的簡介信息是個特例,它放的標籤結構與衆不同,所以咱改下爬蟲文件中的get_detail()函數:

    def get_detail(self,response):
        #獲取電影簡介信息
        description=response.xpath('//div[@id="link-report"]//span[@property="v:summary"]/text()').extract()[0].strip()

在這裏插入圖片描述

(2)第二步:將每個電影的簡介信息放在每個電影的信息裏進行存儲:

1.按咱習慣性的思路:步驟如下

(1)首先:在items.py文件中創建一個用於存儲電影簡介信息的字段

    description=scrapy.Field()

(2)settings.py文件中開啓管道;並設置延時
(3)在爬蟲文件中將電影簡介信息對應到字段裏,並將其返回給管道pipelines.py文件。

    def get_detail(self,response):
        #獲取電影簡介信息
        item=DoubanItem()
        description=response.xpath('//div[@id="link-report"]//span[@property="v:summary"]/text()').extract()[0].strip()
        item['description']=description
        yield item

咱設置爬取首頁25個電影的信息,運行爬蟲之後,觀察我們所獲取到的數據:
在這裏插入圖片描述會發現,電影信息和其簡介信息非但沒有放在一起,而且更嚴重的是,由於scrapy框架採取的是異步方式,所以底下得到的這25個電影的簡介信息也是毫無順序的。這就很頭疼了!

2.既然習慣性的那個思路不行,那這個Scrapy這個這麼牛批的框架的設計者肯定也考慮到這種問題了,所以這裏就引入了meta參數。解決方法如下:

**
注意:這個參數賊牛。那咱如何來理解這個參數的作用:
1.在爬蟲文件將包含電影簡介信息的url請求發送給引擎的同時,會把meta裏的參數也攜帶着;
2.在引擎處理完這個url請求之後會將處理後的response返回給爬蟲文件中我們指定的callback=self.get_detail函數裏的response參數,並且同時會攜帶着這個meta參數。
牛皮之處可見一斑,這就不是變相的將電影基本信息數據和電影簡介信息給拼接到了一起了!!!
**

#修改爬蟲文件裏的parse函數中對應的代碼:
                yield scrapy.Request(detail_url,callback=self.get_detail,meta={"info":item})
                

修改爬蟲文件中咱寫的解析電影簡介信息的函數get_detail()

    def get_detail(self,response):
        item=DoubanItem()
        #獲取電影簡介信息
        #1.meta會跟隨response一塊返回  2.可以通過response.meta接收   3.通過updata可以添加到新的item對象
        info = response.meta["info"]        #接收電影的基本信息
        item.update(info)                   #把電影基本信息的字段加進去
        
        #將電影簡介信息加入相應的字段裏
        description=response.xpath('//div[@id="link-report"]//span[@property="v:summary"]/text()').extract()[0].strip()
        item['description']=description
        yield item

會發現可以很完美的搞到我們所想要的數據:

在這裏插入圖片描述

現在咱又不滿足於只保存在本地txt文本了,咱來試試存儲到數據庫mysql裏怎麼搞呢?(首先,要準備好mysql數據庫以及navicat數據庫可視化管理工具)

(1)分析:如果要同時存儲在本地txt文本里以及mysql數據庫裏,那就需要咱再新建一個管道,並開啓這個管道( settings裏 管道類名添加 ),最後,使用pymysql連接數據庫。

在這裏插入圖片描述

2.新建管道正確代碼:

import pymysql
class DoubanSqlPipeline(object):
    # 1.連接數據庫
    def open_spider(self,spider):
        data_config=spider.settings["DATABASE_CONFIG"]
        if data_config["type"]=="mysql":
            self.conn=pymysql.connect(**data_config["config"])
            self.cursor=self.conn.cursor()

    def process_item(self,item,spider):
        dict(item)
        sql='insert into filminfo (filmname,starname,score,description) values(%s,%s,%s,%s)'
        self.cursor.execute(sql,
                                (
                                    item["film_name"],
                                    item["star_name"],
                                    item["score"],
                                    item["description"],
                                )
                            )
        self.conn.commit()
        return item
    def close_spider(self,spider):
        self.cursor.close()
        self.conn.close()

3.settings.py文件中對連接mysql數據庫的配置:

DATABASE_CONFIG={
    "type":"mysql",
    "config":{
        "host":"localhost",
        "port":3306,
        "user":"root",
        "password":"123456",
        "db":"doubanfilm",
        "charset":"utf8"
    }
}

4.settings.py文件中打開儲存到Mysql數據庫的管道:

在這裏插入圖片描述

5.navicat創庫建表:

創庫:

在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述

最後,運行爬蟲即可。(注意:運行之前,一定要在Mysql裏創建對應的數據庫,表及字段)。運行之後navicat裏效果:在這裏插入圖片描述

2.Scrapy shell的基操:

老是用到Scrapy shell,好奇心驅使着咱來瞅瞅它還能幹啥子?
(1)什麼是Scrapy shell?
用來調試Scrapy 項目代碼的 命令行工具。
啓動的時候預定義了Scrapy的一些對象
(2)它的作用是什麼?
調試!!!

(1)設置shell:

Scrapy 的shell是基於運行環境中的python 解釋器shell

本質上就是通過命令調用shell,並在啓動的時候預定義需要使用的對象

scrapy允許通過在項目配置文件”scrapy.cfg”中進行配置來指定解釋器shell

例如:
[settings]
shell = ipython

(2)啓動shell:

啓動Scrapy shell的命令語法格式如下:

scrapy shell [option] [url或者file]

url 就是你想要爬取的網址

注意:分析本地文件是一定要帶上路徑,scrapy shell默認當作url

(3)終端依此輸入:

fetch(“https://movie.douban.com/top250”) 獲取指定url的response對象

shelp() 這樣是顯示拿到數據之後的一些基操命令!

[s] Available Scrapy objects:
[s]   scrapy     scrapy module (contains scrapy.Request, scrapy.Selector, etc)		#scrapy模塊
[s]   crawler    <scrapy.crawler.Crawler object at 0x0000023948A27A60>				#爬蟲對象
[s]   item       {}		#item對象
[s]   request    <GET https://movie.douban.com/top250>			#請求對象
[s]   response   <200 https://movie.douban.com/top250>			#響應對象
[s]   settings   <scrapy.settings.Settings object at 0x0000023948A27250>			#配置文件
[s]   spider     <DbSpider 'db' at 0x23948efbf70> 								    #爬蟲文件對象
[s] Useful shortcuts:#快捷鍵
[s]   fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s]   fetch(req)                  Fetch a scrapy.Request and update local objects   #獲取url的response對象
[s]   shelp()           Shell help (print this help) 							    #顯示基本命令
[s]   view(response)    View response in a browser								    #會將這個response頁面以網頁形式展示出來

3.Scrapy選擇器

Scrapy提供基於lxml庫的解析機制,它們被稱爲選擇器。
因爲,它們“選擇”由XPath或CSS表達式指定的HTML文檔的某部分。
Scarpy選擇器的API非常小,且非常簡單。

(1)構造selector選擇器

Scrapy選擇器是通過scrapy.Selector類,
通過傳遞文本或者TextResponse對象構造的實例。
(它會根據輸入類型自動選擇最佳解析規則
XML與HTML)

html_str="""
<div class="info">
                    <div class="hd">
                        <a href="https://movie.douban.com/subject/1292052/" class="">
                            <span class="title">肖申克的救贖</span>
                                    <span class="title">&nbsp;/&nbsp;The Shawshank Redemption</span>
                                <span class="other">&nbsp;/&nbsp;月黑高飛(港)  /  刺激1995(臺)</span>
                        </a>


                            <span class="playable">[可播放]</span>
                    </div>
                    <div class="bd">
                        <p class="">
                            導演: 弗蘭克·德拉邦特 Frank Darabont&nbsp;&nbsp;&nbsp;主演: 蒂姆·羅賓斯 Tim Robbins /...<br>
                            1994&nbsp;/&nbsp;美國&nbsp;/&nbsp;犯罪 劇情
                        </p>

                        
                        <div class="star">
                                <span class="rating5-t"></span>
                                <span class="rating_num" property="v:average">9.7</span>
                                <span property="v:best" content="10.0"></span>
                                <span>1983356人評價</span>
                        </div>

                            <p class="quote">
                                <span class="inq">希望讓人自由。</span>
                            </p>
                    </div>
</div>
"""
#########################################第一部分:selector對象的構造
#(1)通過傳遞text文本構造一個selector對象
from scrapy.selector import Selector
sss=Selector(text=html_str)                #通過傳遞text文本構造一個selector對象

print("自動爲我們補全:",sss.extract())            #注意:selector選擇器會自動爲我們補全,最外邊加html標籤和body標籤

#下面兩種效果一樣,我們可以在selector對象上直接使用xpath進行匹配
print("使用文本構造selector對象的使用1:",sss.xpath('./body/div/div/a/span[1]/text()').extract()[0])
print("使用文本構造selector對象的使用2:",sss.xpath('./body/div/div/a/span[1]/text()').extract_first())




#(2)通過response構建selector對象
from scrapy.http import HtmlResponse
response=HtmlResponse(url="http://www.spider.com",body=html_str.encode())  #通過響應構建response對象

#以下共三種方法讓我們可以使用selector對象上的xpath進行匹配。效果一樣!
print("使用響應構造selector對象的使用1:",Selector(response=response).xpath('./body/div/div/a/span[1]/text()').extract()[0])
print("使用響應構造selector對象的使用2:",response.selector.xpath('./body/div/div/a/span[1]/text()').extract()[0])
print("使用響應構造selector對象的使用3:",response.xpath('./body/div/div/a/span[1]/text()').extract()[0])



######################################第二部分:使用選擇器!!!
'''     
選擇器提供2個方法來提取標籤:
(1)xpath()   基於xpath的語法規則 
(2)css()     基於css選擇器的語法規則

使用方法:(快捷方式)
response.xpath()
response.css()

它們返回的是選擇器列表
提取文本:
selector.extract()       返回文本列表
selector.extract_first()或者selector.extract()[0] 返回第一個selector的文本,沒有返回None/
'''
#1.使用css方法:
print("使用css方法:",response.css("a"))
#2.使用xpath方法:
print("使用xpath方法:",response.xpath('./body/div/div/a/span[1]/text()'))
#3.嵌套選擇器的使用:            注意:一定要是selector對象才能混合使用!
print("嵌套選擇器的使用:",response.css("a").xpath('./span[@class="title"]/text()').extract()[0])         #先使用css方法選擇所有的a標籤,再使用xpath匹配。嵌套選擇

'''拓展:
Selector還有一個.re()方法使用正則表達式提取數據的方法。
它返回字符串。
它一般使用在xpath(),css()方法之後,用來過濾文本數據。
re_first()用來返回第一個匹配的字符串。
'''
print("結合使用re:",response.css("a").xpath('./span[@class="title"]/text()').re("的(..)"))         #結合re使用
print("結合使用re的一個快捷方法:",response.css("a").xpath('./span[@class="title"]/text()').re_first("的(..)"))   #從列表中取出第一個

在這裏插入圖片描述

在這裏插入圖片描述

4.Scrapy.spider類

在這裏插入圖片描述

(1)spider的名稱 (name)

一個字符串,用於定義此蜘蛛的名稱。蜘蛛名稱是Scrapy如何定位(並實例化)蜘蛛,因此它必須是唯一的。這是最重要的蜘蛛屬性,它是必需的。

(2)起始urls (start_urls)

蜘蛛將開始爬取的URL列表。因此,下載的第一頁將是此處列出的頁面。後續Request將從起始URL中包含的數據連續生成。

(3)自定義設置 (customer_settings)

運行此蜘蛛時將覆蓋項目範圍的設置。必須將其定義爲類屬性,因爲在實例化之前更新了設置。會覆蓋settings.py文件裏的設置!

在這裏插入圖片描述

(4)日誌器 (logger)

使用Spider創建的Python日誌器。您可以使用它來發送日誌消息。
源碼:
在這裏插入圖片描述

(1)第一種使用方法:Scrapy logger 在每個Spider實例中提供了一個可以訪問和使用的實例(直接在爬蟲文件中使用!)

在這裏插入圖片描述
在本項目中使用:
在這裏插入圖片描述

(2)第二種使用方法:(在其他組件中使用!)

也可以通過python的logging來記錄。比如:logging.warning(‘This is a warning!’)
但是爲了後期維護方面,我們可以創建不同的記錄器來封裝消息。
並且使用組件或函數的名稱進行命名

(此方法在CrawlSpider的使用時進行了使用)
在這裏插入圖片描述

(3)第三種使用方法:(在settings.py配置文件中進行配置!)

##################################日誌的使用:
LOG_FILE='db.log'           #日誌寫入到文件
LOG_ENABLED=False           #表示日誌是否輸出到控制檯。False爲不輸出;True爲輸出。
LOG_ENCODING="utf-8"        #日誌編碼。
LOG_LEVEL="ERROR"           #如果寫INFO,只有大於等於該等級的纔會寫入日誌。

'2020-04-25 10:57:52 [scrapy.utils.log] INFO: Versions: lxml 4.5.0.0, libxml2 2.9.5, cssselect 1.1.0, parsel 1.5.2, w3lib 1.21.0, Twisted 20.3.0, Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)], pyOpenSSL 19.1.0 (OpenSSL 1.1.1f  31 Mar 2020), cryptography 2.9, Platform Windows-10-10.0.18362-SP0'
#             時間    模塊/組件名字  日誌級別     日誌信息
LOG_FORMAT='%(asctime)s [%(name)s] %(levelname)s: %(message)s'
LOG_DATEFORMAT='%Y-%m-%d %H:%M:%S'

LOG_STDOUT=False
LOG_SHORT_NAMES=False

'''下面這些設置可用於配置日誌記錄:

LOG_FILE		日誌輸出文件,如果爲None,就打印在控制檯
LOG_ENABLED	    是否啓用日誌,默認True
LOG_ENCODING   	日誌編碼,默認utf-8
LOG_LEVEL	    日誌等級,默認debug。    EEBUG(調試信息)<INFO(一般信息)<WARNING(警告)<ERROR(一般錯誤)<CRITICAL(嚴重錯誤)
LOG_FORMAT	    日誌格式
LOG_DATEFORMAT	日誌日期格式
LOG_STDOUT	    日誌標準輸出,默認False,如果True所有標準輸出(比如:print)都將寫入日誌中
LOG_SHORT_NAMES 短日誌名,默認爲False,如果True將不輸出組件名

項目中一般設置:
LOG_FILE = 'logfile_name'
LOG_LEVEL = 'INFO'

'''

效果:

在這裏插入圖片描述

(5)創建spider的類方法 (from_crawler)

這是Scrapy用於創建spider的類方法。一般不用覆蓋。
在這裏插入圖片描述

(6)開始請求 (start_requests())

此方法必須返回一個iterable,其中包含第一個要爬網的請求。它只會被調用一次
在這裏插入圖片描述

(7)默認回調函數 (parse(response))

這是Scrapy在其請求未指定回調時處理下載的響應時使用的默認回調。
在這裏插入圖片描述

(8)關閉spider

spider關閉時調用。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章