學習爬蟲之Scrapy框架學習(1)---Scrapy框架初學習及豆瓣top250電影信息獲取的實戰!(seven day)

(1)Scrapy模塊安裝

scrapy支持Python2.7和python3.4以上版本。

python包可以用全局安裝(也稱爲系統範圍),也可以安裝在用戶空間中。

Windows
一.直接安裝
1.在https://www.lfd.uci.edu/~gohlke/pythonlibs/ 下載對應的Twisted的版本文件
2. 在命令行進入到Twisted的目錄 執行pip install 加Twisted文件名

3.執行pip install scrapy
二.annaconda 下安裝 (官方推薦)
1.安裝conda
conda舊版本 https://docs.anaconda.com/anaconda/packages/oldpkglists/
安裝方法 https://blog.csdn.net/ychgyyn/article/details/82119201
2. 安裝scrapy conda install scrapy

(2)Scrapy框架簡介

Scrapy是純Python開發的一個高效,結構化的網頁抓取框架。

Scrapy是個啥?

Scrapy是一個爲了爬取網站數據,提取結構性數據而編寫的應用框架。 其最初是爲了頁面抓取 (更確切來說, 網絡抓取 )所設計的,也可以應用在獲取API所返回的數據(例如 Amazon Associates Web Services ) 或者通用的網絡爬蟲。 Scrapy用途廣泛,可以用於數據挖掘、監測和自動化測試 Scrapy使用了Twisted 異步網絡庫來處理網絡通訊。

我們爲啥要用這玩意呢?

1.爲了更利於我們將精力集中在請求與解析上。
2.企業級的要求。

(3)運行流程

(只要提到框架,就要重視它的運行流程/邏輯順序)

引入:

在這裏插入圖片描述舉個粟子:
大一新生小明開學,他先到新生接待處等待,老學長學姐(管理人員)看到了就會上前詢問你需要幫忙嘛?小明正愁不知道該幹啥,就說我是來報道的大一新生,管理人員聽了就會將你的信息進行排隊,等排隊到了小明之後,就會將這個號給到管理人員。
然後,管理人員將這個號給到報到處,報到處安排小明的在校信息,比如:班級,宿舍…並將這些信息返還給管理人員。管理人員得到之後會再將這些信息給小明這個大一新生,讓小明覈對下這些是不是自己所需的,經小明認真核對之後發現都是自己想要的,小明跟管理人員說:我已經確認過了就這樣哦!
最後,管理人員就會將這些信息交到信息管理處進行存儲。

注意:圖中的弧線的意義:
如果,在小明拿到信息覈對之後發現這些不是自己所需的,那麼,小明就會告訴管理人員,這些不是我所要的,我要重新請求一下別的東西,然後管理人員就就會將小明進行重新排隊!!!

1.進入正題:

在這裏插入圖片描述
spiders網頁爬蟲
items項目
engine引擎
scheduler調度器
downloader下載器
item pipelines項目管道
middleware中間設備,中間件

數據流:
上圖顯示了Scrapy框架的體系結構及其組件,以及系統內部發生的數據流(由紅色的箭頭顯示。)
Scrapy中的數據流由執行引擎控制,流程如下:

首先從網頁爬蟲獲取初始的請求
將請求放入調度模塊,然後獲取下一個需要爬取的請求
調度模塊返回下一個需要爬取的請求給引擎
引擎將請求發送給下載器,依次穿過所有的下載中間件
一旦頁面下載完成,下載器會返回一個響應包含了頁面數據,然後再依次穿過所有的下載中間件。
引擎從下載器接收到響應,然後發送給爬蟲進行解析,依次穿過所有的爬蟲中間件
爬蟲處理接收到的響應,然後解析出item和生成新的請求,併發送給引擎
引擎將已經處理好的item發送給管道組件,將生成好的新的請求發送給調度模塊,並請求下一個請求
該過程重複,直到調度程序不再有請求爲止。

中間件介紹:

(1)下載中間件
下載中間件是位於引擎和下載器之間的特定的鉤子,它們處理從引擎傳遞到下載器的請求,以及下載器傳遞到引擎的響應。
如果你要執行以下操作之一,請使用Downloader中間件:
在請求發送到下載程序之前處理請求(即在scrapy將請求發送到網站之前)
在響應發送給爬蟲之前
直接發送新的請求,而不是將收到的響應傳遞給蜘蛛
將響應傳遞給爬行器而不獲取web頁面;
默默的放棄一些請求

(2)爬蟲中間件
爬蟲中間件是位於引擎和爬蟲之間的特定的鉤子,能夠處理傳入的響應和傳遞出去的item和請求。
如果你需要以下操作請使用爬蟲中間件:
處理爬蟲回調之後的請求或item
處理start_requests
處理爬蟲異常
根據響應內容調用errback而不是回調請求

2.各個組件介紹:

Scrapy Engine(引擎)
引擎負責控制系統所有組件之間的數據流,並在發生某些操作時觸發事件。

scheduler(調度器)
調度程序接收來自引擎的請求,將它們排入隊列,以便稍後引擎請求它們。

Downloader(下載器)
下載程序負責獲取web頁面並將它們提供給引擎,引擎再將它們提供給spider。

spider(爬蟲)
爬蟲是由用戶編寫的自定義的類,用於解析響應,從中提取數據,或其他要抓取的請求。

Item pipeline(管道)
管道負責在數據被爬蟲提取後進行後續處理。典型的任務包括清理,驗證和持久性(如將數據存儲在數據庫中)

(3)簡單使用

1.基操(簡單的項目命令)!

(1)創建項目:


小知識點:<>爲必填項;[]爲選填項!
小技巧1:pycharm終端輸入scrapy可以查看一些幫助,有助於我們寫那些難記的命令!
小技巧2:scrapy+命令關鍵字,可以查看有關於此命令的詳細用法!

1.首先:
cd+要放scrapy項目的文件夾路徑

2.第二步:
通過scrapy命令可以很方便的新建scrapy項目。

語法格式:scrapy startproject <project_name> [project_dir]

該命令會在project_dir文件加下創建一個名爲project_name的Scrapy新項目。如果project_dir沒有指定,project_dir與project_name相同。
執行命令:
scrapy startproject baidu
之後會在指定文件夾創建如下文件:

在這裏插入圖片描述

(2)創建爬蟲文件

{
創建一個bdSpider的類,它必須繼承scrapy.Spider類,需要定義以下三個屬性:
name: spider的名字,必須且唯一
start_urls: 初始的url列表
parse(self, response) 方法:每個初始url完成之後被調用。這個函數要完成一下兩個功能:
解析響應,封裝成item對象並返回這個對象
提取新的需要下載的url,創建新的request,並返回它

我們也可以通過命令創建爬蟲

語法格式:scrapy genspider [-t template]
運行命令:scrapy genspider bd www.baidu.com
會在spiders文件下生成bd.py文件
}
1.首先:
cd 到項目下
2.第二步:
scrapy genspider [options]
scrapy genspider bd www.baidu.com
會創建在項目/spider下 ;其中bd 是爬蟲文件名, www.baidu.com 是 url(域名)
執行命令:
scrapy genspider bd www.baidu.com
之後再項目/spider下創建的文件爲:

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


class BdSpider(scrapy.Spider):          #繼承了scrapy.Spider類
    name = 'bd'                         #名字是唯一的(不重複)  因爲我們在啓動項目的時候,是根據這個名字來找爬蟲文件的
    allowed_domains = ['www.baidu.com'] #允許的域名 (限制)    可以沒有這個限制!
    start_urls = ['http://www.baidu.com/']  #首個請求(必須要有)  不然開始都開始不了,怎麼讓整個框架運行下去呢!

    def parse(self, response):           #必須是parse函數  不可以亂改名  接收下載器下載的數據
        print("*******")		#用於更直觀的觀察框架能否正常運行!
        print("*******")
        print("*******")
        print("*******")
        print("*******")
        print("*******")
        print(response)         #response對象
        #獲取數據   兩種方法:
        print(response.body.decode())   #獲取到的是字節碼形式
        # print(response.text)

注意:最後引擎給spider模塊的數據就給到了函數parse裏的形參response:
在這裏插入圖片描述

(3)運行爬蟲文件

一步即可:
scrapy crawl [options]
其中spider是爬蟲文件名

執行命令:
scrapy crawl bd

但是!我們運行爬蟲文件之後,發現用於測試的print函數沒有顯示,經過檢查終端輸出的數據可知Scrapy框架是默認遵循robots協議的,所以咱們肯定獲取不到數據了!!!

在這裏插入圖片描述

如何解決這個問題呢?

打開設置文件settings.py,將其中的以下代碼更改爲False即可!

# Obey robots.txt rules
ROBOTSTXT_OBEY = True

(2)實操(豆瓣電影top250首頁電影信息的獲取!)

1.創建項目:

scrapy startproject douban

2.創建爬蟲文件:

scrapy genspider db www.summer.com
(注意:這個域名是可以隨便寫的【但是必須要寫哦!】,等爬蟲文件生成之後再進相應的爬蟲文件改爲我們所需的即可!)

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


class DbSpider(scrapy.Spider):
    name = 'db'
    allowed_domains = ['movie.douban.com']
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        print("*********")
        print("*********")
        print("*********")
        print("*********")
        print("*********")
        print(response.text)

3.運行爬蟲文件:

scrapy crawl db
但是,我們運行之後發現又沒有獲取到數據哎!
在這裏插入圖片描述
造成這樣的原因是:回想爬蟲的基礎,我們如果直接這樣向網頁發送請求進行爬取,那服務端一眼就看到咱是scrapy了,它還會理咱嘛?所以我們要設置請求頭!

4.設置請求頭:

在配置文件settings.py中找到如下代碼取消註釋並加入爬取網頁請求頭的User-Agent即可!
在這裏插入圖片描述

5.獲取到電影名字:

{
到現在,我們運行爬蟲文件,Scrapy框架已經可以獲取到網頁的首頁數據。那麼,我們如何篩選出我們想要的電影的名字呢?
考慮到我們如果利用xpath匹配,可能要多次嘗試才能正確匹配到,那就需要我們一次又一次的運行咱的項目,多麻煩啊!咱都這樣想了,人家大牛也這樣想啊,所以,在這裏有個賊帥賊帥的牛皮的方法:
使用shell交互式平臺:(注意1:它是遵循settings設置的;注意2:一定要到咱的項目文件夾下運行;)
首先:cd到我們項目的文件路徑下。
然後:輸入命令scrapy shell url (start_url) 即可!
這樣:它其實就請求到了此url的數據(跟上面運行爬蟲文件得到的數據一模一樣)!!!
}

首先:打開我們的shell交互式平臺。
再此項目中:輸入命令scrapy shell https://movie.douban.com/top250
第二步:在shell交互式平臺中匹配我們所需的電影數據。
輸入:response.xpath(’//div[@class=“info”]/div/a/span[1]/text()’)

在這裏插入圖片描述
會發現:這得到的是一個selector對象!
而我們得到的數據就是用的response對象自帶的xpath匹配到的(生成了response之後就會自動生成selector對象)!
與我們正常用的xpath不同,它獲取到的數據在selector對象裏,如上圖:

第三步:從selector對象中提取電影名字
使用selector對象的方法.extract()。這個方法可以提取到selector對象中data對應的數據。
response.xpath(’//div[@class=“info”]/div/a/span[1]/text()’).extract()
在這裏插入圖片描述

6.將獲取到的電影的信息存儲到text文本中

{
注意:如果想要存儲數據,就要用到管道。
這就涉及到了items.py文件(定義結構化數據字段)和pipelines.py文件(管道文件)。
}
首先:操作items.py文件
因爲我們只需要存儲一個信息,所以定義一個字段名即可!
{
定義公共輸出數據格式,Scrapy提供了Item類。Item對象是用於收集剪貼數據的簡單容器。它們提供了一個類似詞典的API,提供了一種方便的語法來聲明它們的可用字段。 scray.Item對象是用於收集抓取數據的簡單容器,使用方法和python的字典類似。編輯項目目錄下items.py文件。

然後我們只需要在爬蟲中導入我們定義的Item類,實例化後用它進行數據結構化。
}

# -*- 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()   #定義字段名

第二步:在爬蟲文件中操作數據,使其與管道建立橋樑
{
到目前爲止,我們通過scrapy寫出的爬蟲還看不出優越性在哪裏,並且上面的爬蟲還有個很嚴重的問題,就是對文件的操作。每次調用parse方法會打開文件關閉文件,這極大的浪費了資源。parse函數在解析出我們需要的信息之後,可以將這些信息打包成一個字典對象或scray.Item對象(一般都是item對象),然後返回。這個對象會被髮送到item管道,該管道會通過順序執行幾個組件處理它。每個item管道組件是一個實現簡單方法的Python類。他們收到一個item並對其執行操作,同時決定該item是否應該繼續通過管道或者被丟棄並且不再處理。
item管道的典型用途是:

清理HTML數據
驗證已刪除的數據(檢查項目是否包含某些字段)
檢查重複項(並刪除它們)
將已爬取的item進行數據持久化
}

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

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

class DbSpider(scrapy.Spider):
    name = 'db'
    allowed_domains = ['movie.douban.com']
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        # 獲取電影信息數據
        films1_name=response.xpath('//div[@class="info"]/div/a/span[1]/text()').extract()
        # 交給管道存儲
        # 使用DoubanItem
        item=DoubanItem()  #創建對象
        item["films_name"]=films1_name      #值是個列表,因爲xpath匹配到的數據都扔到列表裏了!
        # item可以理解爲一個安全的字典  用法與字典相同
        print("item裏面是:",dict(item))  #可以轉換爲字典
        return item     #交給引擎  引擎要交給管道,需要打開管道



第三步:我們要將數據提交給管道,所以需要打開管道
要激活這個管道組件,必須將其添加到ITEM_PIPELINES設置中,在settings.py文件中:

(在此設置中爲類分配的整數值決定了它們運行的順序:按照從較低值到較高值的順序進行。
注意:這個管道的目的只是介紹如何編寫項目管道,如果要將所有爬取的item存儲到json文件中,則應使用Feed導出,在運行爬蟲是加上如下參數:
scrapy crawl bd -o films.json)

在這裏插入圖片描述

第四步:現在數據已經可以交給管道,那麼管道就要對數據進行處理
就是操作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 process_item(self, item, spider):
        #爲了能寫進text  json.dumps將dic數據轉換爲str
        json_str=json.dumps(dict(item),ensure_ascii=False)
        with open("films.text","w",encoding="utf-8") as f:
            f.write(json_str)
        return item

實現效果:

在這裏插入圖片描述

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