學習爬蟲之Scrapy框架學習(2)---豆瓣top250電影更加詳細的信息獲取及txt文本存儲外加settings.py配置文件的學習!(eight day)

前言:
昨天使用Scrapy框架簡單爬取並下載了豆瓣Top250首頁的排名前25個電影的電影名。
感覺略過寒酸,今天咱就來仔細搞一搞,搞到更加詳細的信息!!!

1.首先,我們知道改變我們提取的數據是在我們的spider爬蟲文件裏的parse函數下進行操作的!

(注意哦!咱這個parse函數就是來解析和提取數據的!!!)

(1)那麼,既然我們要獲取更加詳細的信息,我們就要來分析網頁源碼:(經過簡單觀察之後,我們發現,這25個電影的各自的所有信息都分別放在了class屬性值爲info的div標籤裏,那麼,我們要提取出這些電影的信息的話,就要首先提取到這些特定的div標籤,然後再對這些個div標籤進行操作即可!)

‘’‘
網頁源碼剖析:
<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>
‘’‘

2.其次:既然要分析如何分別匹配到各個電影的詳細的信息,那麼我們就考慮使用scrapy shell來十分方便快捷的進行各種嘗試

(1)終端進入scrapy shell交互式界面命令:

scrapy shell https://movie.douban.com/top250

(2)首先,分析下咱剛剛那個思想是否正確(每個電影的信息都藏在class屬性值爲info的div中)在這裏插入圖片描述

這就說明咱的分析是沒得錯的!

(2)第二步,分析如何獲取到電影名字

1.首先,咱嘗試下獲取下第一個電影的電影名字。結合源碼使用xpath匹配:

在這裏插入圖片描述

2.然後,一個電影的名字咱都獲取成功了,使用循環嘗試能否成功獲取到25個電影名字:在這裏插入圖片描述

會發現灰常的成功哦!

(3)第三步:分析如何獲取到電影的主演:

1.首先,觀察網頁源碼可知:這個主演所在的標籤裏面非常混亂,所以,咱先嚐試匹配出25個電影的主演所在的標籤:

包含電影主演的標籤:
在這裏插入圖片描述

在這裏插入圖片描述也是非常的成功!!!

2.第二步:我們要想辦法匹配到每一個電影的主演的名字,但是!觀察剛剛匹配到25個電影的包含主演的標籤的text信息可知,這裏面有坑哦!有些電影不一定有主演:

在這裏插入圖片描述

所以,咱再匹配這25個電影的主演名字的時候,一定要注意使用判斷避坑!(見下:)

            if "主" in con_star_name:
                star_name=re.findall("主演?:? ?(.*)",con_star_name)[0]
            else:
                star_name="空"

(4)分析如何獲取電影的評分:

1.首先,咱嘗試下獲取下第一個電影的評分。結合源碼使用xpath匹配:在這裏插入圖片描述

又是美好的成功哦!

2.然後,一個電影的評分咱都獲取成功了,使用循環嘗試能否成功獲取到25個電影的評分:在這裏插入圖片描述

非常的完美!

總結:

    def parse(self, response):  #解析和提取數據
        # 獲取電影信息數據
        # films_name=response.xpath('//div[@class="info"]/div/a/span[1]/text()').extract()
        node_list=response.xpath('//div[@class="info"]')    #25個
        for node in node_list:
            # 電影名字
            film_name=node.xpath('./div/a/span[1]/text()').extract()[0]
            # 主演   拿標籤內容,再正則表達式匹配
            con_star_name=node.xpath('./div/p[1]/text()').extract()[0]
            if "主" in con_star_name:
                star_name=re.findall("主演?:? ?(.*)",con_star_name)[0]
            else:
                star_name="空"
            #評分
            score=node_list.xpath('./div/div/span[@property="v:average"]/text()').extract()[0]

2.然後,數據已經解析並且可以正確的提取到我們想要的數據。下一步就是將其交給管道進行儲存。

(1)首先,引擎交給spider(爬蟲文件)的信息已經被爬蟲解析並提取正確的信息,下一步是spider(爬蟲文件)將數據再次交給引擎,而能否成功交給引擎,這就取決於items.py文件(定義結構化數據字段)是否有對應的字段名等待插入數據:

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy


class DoubanItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    #需要定義字段名  就像數據庫那樣,有字段名,才能插入數據(即存儲數據)
    # films_name=scrapy.Field()   #定義字段名
    film_name=scrapy.Field()
    star_name=scrapy.Field()
    score=scrapy.Field()

(2)第二步,items.py文件中已經創建好字段名等待插入數據了,那麼,爬蟲文件裏就要將數據一一對應字段名:

#在剛剛的爬蟲文件的循環下寫入即可:
            # 使用字段名  收集數據
            item=item=DoubanItem()
            item["film_name"]=film_name
            item["star_name"]=star_name
            item["score"]=score

注意:在settings.py文件中開啓管道並關閉robots協議!

(3)第三步:引擎將數據交給管道的中間的item這一步已經成功走過去了,下一步就是如何將數據返回給管道:在這裏要注意一個問題:慣性思維會讓我們在這個函數裏定性的使用return返回item,但是,切記return返回的是parse這個方法(會造成只會傳給管道第一個電影信息的bug)。而我們所需要的是返回每次解析後的數據,so我們想到了生成器,使用yield返回,這樣每搞一次數據出來,生成器就給一次數據,循環如此,非常nice!!!

#我們只需在爬蟲文件的循環最底下加入即可:
			             # 形式:{"film_name":"肖申克的救贖","star_name":"蒂姆","score":"9.7"}

						 yield item

(4)第四步:引擎已經將數據交給管道(即pipelines.py管道文件),但是,我們這是25個請求,就會進行25次處理,也就意味着,引擎會交給管道25次數據,那麼在我們在管道里進行儲存數據的時候,按往常來說就要來來回回打開關閉文件,進行數據的寫入。這樣顯然不好。所以:在此引入管道文件裏的兩種牛批的方法:

#爬蟲文件開啓,此方法就開啓
def open_spider(self,spider):
	pass
	
#爬蟲文件關閉,此方法就開啓
def close_spider(self,spider):
	pass

這就非常合我們的需求,結合這兩個方法,我們只需要在open_spider()方法里加入打開文件操作;在close_spider()方法里加入關閉文件操作即可,這樣就避免了文件的來來回回的開啓關閉,好處不言而喻。

來看看酷炫吊炸天的升級版的pipelines.py文件(管道文件):

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html

import json
class DoubanPipeline(object):
    def open_spider(self,spider):   #爬蟲文件開啓,此方法就開啓
        self.f=open("films.txt","w",encoding="utf-8")       #打開文件

    def process_item(self, item, spider):        #會來25次,就會調用25次這個方法  如果按常規來寫,文件就會被操作25次打開關閉
        #爲了能寫進text  json.dumps將dic數據轉換爲str
        json_str=json.dumps(dict(item),ensure_ascii=False)+"\n"
        self.f.write(json_str)                              #爬蟲文件開啓時,文件就已經打開,在此直接寫入數據即可!
        return item

    def close_spider(self,spider):  #爬蟲文件關閉,此方法就開啓
        self.f.close()                                      #爬蟲文件關閉時,引擎已經將全部數據交給管道,關閉文件


3.爬取豆瓣Top250首頁25個電影的更多的信息已經實現,效果如下:在這裏插入圖片描述

拓展:剛剛咱們實現了豆瓣首頁25個電影信息的爬取,那麼,如果我們想要爬取更多頁(比如:10頁)該怎麼做呢?

(1)首先,分析如何爬取兩頁,注意:Scrapy框架運行的流程,任何模塊發出的請求都是給到引擎的,所以,我們只需要在爬蟲文件中的第一次請求的數據提交給管道之後,使用yield發起一個請求(豆瓣電影Top250第二頁的url),那麼,這個請求就會自動的交給了引擎,就開啓了新一輪的自動化走流程,但是,再最後引擎需要將數據再送給spider爬蟲文件讓其解析並獲取真正想要存儲到管道的數據,所以就需要callback回調自身這個parse函數。

邏輯如下圖:
在這裏插入圖片描述

(2)獲取兩頁的信息都可以實現了,那麼獲取更多(比如:10頁),只要找到每頁url的規律,給個循環就OK啦!

1.剖析每頁url可知:每加一頁,對應的start參數的值就會加25。

'''
各頁url規律剖析:
https://movie.douban.com/top250
https://movie.douban.com/top250?start=0&filter=
https://movie.douban.com/top250?start=25&filter=
https://movie.douban.com/top250?start=50&filter=
'''

2.在爬蟲文件每個請求執行完成功之後,利用格式化輸出.format()方法向引擎發送每頁的請求即可!(每完成一個請求的全部流程,page_num就會加一,25倍的page_num就對應了每頁url的start參數的值;注意:我們會發現總共就10頁有信息,多了就沒得信息了,所以設置了if判斷,如果url獲取的信息爲空,就返回空,引擎接到空的請求,就會自動關閉)

# -*- coding: utf-8 -*-
import scrapy
import re

from ..items import DoubanItem      #因爲我們要使用包含定義字段名的類,所以需要導入

class DbSpider(scrapy.Spider):
    name = 'db'
    allowed_domains = ['movie.douban.com']
    start_urls = ['https://movie.douban.com/top250']
    page_num=0   #類變量
    def parse(self, response):  #解析和提取數據
        # 獲取電影信息數據
        # films_name=response.xpath('//div[@class="info"]/div/a/span[1]/text()').extract()
        node_list=response.xpath('//div[@class="info"]')    #25個
        if node_list:       #此判斷的作用:在爬取到10頁之後,就獲取不到了!判斷每次是否獲取到數據,如果沒有則返回空(即停止了)
            for node in node_list:
                # 電影名字
                film_name=node.xpath('./div/a/span[1]/text()').extract()[0]
                # 主演   拿標籤內容,再正則表達式匹配
                con_star_name=node.xpath('./div/p[1]/text()').extract()[0]
                if "主" in con_star_name:
                    star_name=re.findall("主演?:? ?(.*)",con_star_name)[0]
                else:
                    star_name="空"
                #評分
                score=node_list.xpath('./div/div/span[@property="v:average"]/text()').extract()[0]

                # 使用字段名  收集數據
                item=item=DoubanItem()
                item["film_name"]=film_name
                item["star_name"]=star_name
                item["score"]=score

                 # 形式:{"film_name":"肖申克的救贖","star_name":"蒂姆","score":"9.7"}
                yield item          #不使用return的原因是,return返回的是parse這個方法(會造成只會傳給管道第一個電影信息的bug)。而我們所需要的是返回每次解析後的數據
            self.page_num+=1
            print("page_num:",self.page_num)
            page_url="https://movie.douban.com/top250?start={}&filter=".format(self.page_num*25)
            yield scrapy.Request(page_url, callback=self.parse)
            # 注意:各個模塊的請求都會交給引擎,然後經過引擎的一系列操作;但是,切記:引擎最後要把得到的數據再來給到
            # spider爬蟲文件讓它解析並獲取到真正想要的數據(callback=self.parse)這樣就可以再給到自身。
        else:
            return

'''
各頁url規律剖析:
https://movie.douban.com/top250
https://movie.douban.com/top250?start=0&filter=
https://movie.douban.com/top250?start=25&filter=
https://movie.douban.com/top250?start=50&filter=
'''




'''
網頁源碼剖析:
<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>
'''

切記:
要在settings.py文件中開啓延時。
不然:服務器很容易檢測出來,後果嚴重!!!

在這裏插入圖片描述

運行會發現很棒哦!

在這裏插入圖片描述

拓展:來仔細研讀研讀settings.py配置文件!

# -*- coding: utf-8 -*-

# Scrapy settings for douban project
#
# For simplicity, this file contains only settings considered important or
# commonly used. You can find more settings consulting the documentation:
#
#     https://docs.scrapy.org/en/latest/topics/settings.html
#     https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#     https://docs.scrapy.org/en/latest/topics/spider-middleware.html

BOT_NAME = 'douban'                     #scrapy項目名字

SPIDER_MODULES = ['douban.spiders']     #爬蟲模塊
NEWSPIDER_MODULE = 'douban.spiders'     #使用genspider命令創建的爬蟲模塊


# Crawl responsibly by identifying yourself (and your website) on the user-agent
#USER_AGENT = 'douban (+http://www.yourdomain.com)'         #默認的User_Agent   用戶代理

# Obey robots.txt rules
ROBOTSTXT_OBEY = False              #機器人協議

#配置         最大     併發       請求     通過scrapy執行的
# Configure maximum concurrent requests performed by Scrapy (default: 16)       #併發請求的最大值,默認是16。
#CONCURRENT_REQUESTS = 32

#設置網站請求延遲       默認是0
# Configure a delay for requests for the same website (default: 0)
# See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
DOWNLOAD_DELAY = 2              #2秒
# The download delay setting will honor only one of:
#CONCURRENT_REQUESTS_PER_DOMAIN = 16            #單個域名允許的併發請求  16個           注意:一個域名可以對應多個IP
#CONCURRENT_REQUESTS_PER_IP = 16                #單個IP允許的併發請求    16個

# Disable cookies (enabled by default)
#COOKIES_ENABLED = False            #設置是否使用cookies

# Disable Telnet Console (enabled by default)
#TELNETCONSOLE_ENABLED = False          #設置是否使用監控控制檯

# Override the default request headers:
DEFAULT_REQUEST_HEADERS = {             #設置全局的請求頭
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
    # 爬取網頁的請求頭中的User-Agent
  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Safari/537.36"
}

# Enable or disable spider middlewares          #是否打開爬蟲中間件(類)的封印
# See https://docs.scrapy.org/en/latest/topics/spider-middleware.html
#SPIDER_MIDDLEWARES = {
#    'douban.middlewares.DoubanSpiderMiddleware': 543,
#}

# Enable or disable downloader middlewares      #是否打開下載器中間件(類)的封印
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#DOWNLOADER_MIDDLEWARES = {
#    'douban.middlewares.DoubanDownloaderMiddleware': 543,
#}

# Enable or disable extensions                  #擴展程序
# See https://docs.scrapy.org/en/latest/topics/extensions.html
#EXTENSIONS = {
#    'scrapy.extensions.telnet.TelnetConsole': None,
#}

# Configure item pipelines                      #設置管道   管道是一個類,可以設置優先級(0-1000),越小則級別越高
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# ITEM_PIPELINES = {
#    'douban.pipelines.DoubanPipeline': 200,
#    'douban.pipelines.DoubanSqlPipeline': 300,
# }

#啓用或配置       AutoThrottle   拓展
# Enable and configure the AutoThrottle extension (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/autothrottle.html
#AUTOTHROTTLE_ENABLED = True

#初始下載延遲
# The initial download delay
#AUTOTHROTTLE_START_DELAY = 5

#在高延遲情況下設置最大下載延遲
# The maximum download delay to be set in case of high latencies
#AUTOTHROTTLE_MAX_DELAY = 60

#每個遠程服務器並行發送的請求的平均數
# The average number of requests Scrapy should be sending in parallel to
# each remote server
#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0

#啓用顯示收到的每個響應的調節信息
# Enable showing throttling stats for every response received:
#AUTOTHROTTLE_DEBUG = False

#啓用配置默認緩存
# Enable and configure HTTP caching (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
#HTTPCACHE_ENABLED = True
#HTTPCACHE_EXPIRATION_SECS = 0
#HTTPCACHE_DIR = 'httpcache'
#HTTPCACHE_IGNORE_HTTP_CODES = []
#HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'

DATABASE_CONFIG={
    "type":"mysql",
    "config":{
        "host":"localhost",
        "port":3306,
        "user":"root",
        "password":"123456",
        "db":"spider39",
        "charset":"utf8"
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章