1. 程式人生 > >Scrapy 框架入門簡介

Scrapy 框架入門簡介

其中 都是 style mts 實現 json格式 pin 一次 pywin32

一、Scrapy框架簡介

Scrapy 是用 Python 實現的一個為了爬取網站數據、提取結構性數據而編寫的應用框架。

Scrapy 常應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。

通常我們可以很簡單的通過 Scrapy 框架實現一個爬蟲,抓取指定網站的內容或圖片。

二、Scrapy架構圖(綠線是數據流向)

技術分享圖片

  • Scrapy Engine(引擎): 負責Spider、ItemPipeline、Downloader、Scheduler中間的通訊,信號、數據傳遞等。

  • Scheduler(調度器): 它負責接受引擎發送過來的Request請求,並按照一定的方式進行整理排列,入隊,當引擎需要時,交還給引擎(主要功能url去重,構建url隊列)。

  • 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的運作流程

代碼寫好,程序開始運行...

1 引擎:Hi!Spider, 你要處理哪一個網站?

2 Spider:老大要我處理xxxx.com。

3 引擎:你把第一個需要處理的URL給我吧。

4 Spider:給你,第一個URL是xxxxxxx.com。

5 引擎:Hi!調度器,我這有request請求你幫我排序入隊一下。

6 調度器:好的,正在處理你等一下。 7 引擎:Hi!調度器,把你處理好的request請求給我。 8 調度器:給你,這是我處理好的request 9 引擎:Hi!下載器,你按照老大的下載中間件的設置幫我下載一下這個request請求 10 下載器:好的!給你,這是下載好的東西。(如果失敗:sorry,這個request下載失敗了。然後引擎告訴調度器,這個request下載失敗了,你記錄一下,我們待會兒再下載) 11 引擎:Hi!Spider,這是下載好的東西,並且已經按照老大的下載中間件處理過了,你自己處理一下(註意!這兒responses默認是交給def parse()這個函數處理的) 12 Spider:(處理完畢數據之後對於需要跟進的URL),Hi!引擎,我這裏有兩個結果,這個是我需要跟進的URL,還有這個是我獲取到的Item數據。 13 引擎:Hi !管道 我這兒有個item你幫我處理一下!調度器!這是需要跟進URL你幫我處理下。然後從第四步開始循環,直到獲取完老大需要全部信息。 14 管道``調度器:好的,現在就做!

註意!只有當調度器中不存在任何request了,整個程序才會停止,(也就是說,對於下載失敗的URL,Scrapy也會重新下載。)

四、制作 Scrapy 爬蟲 一共需要5步:

#新建項目 :新建一個新的爬蟲項目
scrapy startproject proName

#創建爬蟲文件
scrapy genspider spiName "www.xxx.com"

#明確目標 (編寫items.py):明確你想要抓取的目標

#編寫爬蟲文件:制作爬蟲開始爬取網頁

#存儲內容 (pipelines.py):設計管道存儲爬取內容

五、Scrapy的安裝

Windows 安裝方式

a. pip3 install wheel
b. pip3 install Twisted-17.0.1-cp35-cp35m-win_amd64.whl
c. pip3 install pywin32
d. pip3 install scrapy

六、入門案例

(一)在開始爬取之前,必須創建一個新的Scrapy項目。進入自定義的項目目錄中,運行下列命令:

scrapy startproject mySpider

其中, mySpider 為項目名稱,可以看到將會創建一個 mySpider 文件夾,目錄結構大致如下:

下面來簡單介紹一下各個主要文件的作用:

mySpider/
    scrapy.cfg
    mySpider/
        __init__.py
        items.py
        pipelines.py
        settings.py
        spiders/
            __init__.py
            ...

這些文件分別是:

  • scrapy.cfg: 項目的配置文件。
  • mySpider/: 項目的Python模塊,將會從這裏引用代碼。
  • mySpider/items.py: 項目的目標文件。
  • mySpider/pipelines.py: 項目的管道文件。
  • mySpider/settings.py: 項目的設置文件。
  • mySpider/spiders/: 存儲爬蟲代碼目錄。

(二)明確目標

我們打算抓取 http://www.itcast.cn/channel/teacher.shtml 網站裏的所有講師的姓名、職稱和個人信息。

    1. 打開 mySpider 目錄下的 items.py。

    2. Item 定義結構化數據字段,用來保存爬取到的數據,有點像 Python 中的 dict,但是提供了一些額外的保護減少錯誤。

    3. 可以通過創建一個 scrapy.Item 類, 並且定義類型為 scrapy.Field 的類屬性來定義一個 Item(可以理解成類似於 ORM 的映射關系)。

接下來,創建一個 ItcastItem 類,和構建 item 模型(model)。

import scrapy

class ItcastItem(scrapy.Item):
   name = scrapy.Field()
   title = scrapy.Field()
   info = scrapy.Field()

(三)制作爬蟲文件

1. 爬數據

在當前目錄下輸入命令,將在mySpider/spider目錄下創建一個名為itcast的爬蟲,並指定爬取域的範圍:

scrapy genspider itcast "itcast.cn"

打開 mySpider/spider目錄裏的 itcast.py,默認增加了下列代碼:

import scrapy

class ItcastSpider(scrapy.Spider):
    name = "itcast"
    allowed_domains = ["itcast.cn"]
    start_urls = (
        http://www.itcast.cn/,
    )

    def parse(self, response):
        pass

其實也可以由我們自行創建itcast.py並編寫上面的代碼,只不過使用命令可以免去編寫固定代碼的麻煩

要建立一個Spider, 你必須用scrapy.Spider類創建一個子類,並確定了三個強制的屬性 和 一個方法。

name = "" :這個爬蟲的識別名稱,必須是唯一的,在不同的爬蟲必須定義不同的名字。

allow_domains = [ ] 是搜索的域名範圍,也就是爬蟲的約束區域,規定爬蟲只爬取這個域名下的網頁,不存在的URL會被忽略。

start_urls = () :爬取的URL元祖/列表。爬蟲從這裏開始抓取數據,所以,第一次下載的數據將會從這些urls開始。其他子URL將會從這些起始URL中繼承性生成。

parse(self, response) :解析的方法,每個初始URL完成下載後將被調用,調用的時候傳入從每一個URL傳回的Response對象來作為唯一參數,主要作用如下:

負責解析返回的網頁數據(response.body),提取結構化數據(生成item)
生成需要下一頁的URL請求。
將start_urls的值修改為需要爬取的第一個url

start_urls = ("http://www.itcast.cn/channel/teacher.shtml",)

2、取數據,修改parse()方法

from mySpider.items import ItcastItem

def parse(self, response):
    #open("teacher.html","wb").write(response.body).close()

    # 存放老師信息的集合
    items = []

    for each in response.xpath("//div[@class=‘li_txt‘]"):
        # 將我們得到的數據封裝到一個 `ItcastItem` 對象
        item = ItcastItem()
        #extract()方法返回的都是unicode字符串
        name = each.xpath("h3/text()").extract()
        title = each.xpath("h4/text()").extract()
        info = each.xpath("p/text()").extract()

        #xpath返回的是包含一個元素的列表
        item[name] = name[0]
        item[title] = title[0]
        item[info] = info[0]

        items.append(item)

    # 直接返回最後數據
    return items

我們暫時先不處理管道,此時保存數據可以在終端輸入命令,指定-o參數

scrapy保存信息的最簡單的方法主要有四種,-o 輸出指定格式的文件,命令如下:

scrapy crawl itcast -o teachers.json      #json格式,默認為Unicode編碼

scrapy crawl itcast -o teachers.jsonlines    #json lines格式,默認為Unicode編碼

scrapy crawl itcast -o teachers.csv    #csv 逗號表達式,可用Excel打開

scrapy crawl itcast -o teachers.xml   #xml格式

如果將return改成yield,如下所示,yield會將item數據通過引擎提交給管道進行數據的存儲

from mySpider.items import ItcastItem

def parse(self, response):
    #open("teacher.html","wb").write(response.body).close()

    # 存放老師信息的集合
    #items = []

    for each in response.xpath("//div[@class=‘li_txt‘]"):
        # 將我們得到的數據封裝到一個 `ItcastItem` 對象
        item = ItcastItem()
        #extract()方法返回的都是unicode字符串
        name = each.xpath("h3/text()").extract()
        title = each.xpath("h4/text()").extract()
        info = each.xpath("p/text()").extract()

        #xpath返回的是包含一個元素的列表
        item[name] = name[0]
        item[title] = title[0]
        item[info] = info[0]

        #items.append(item)

        #將獲取的數據交給pipelines
        yield item

此時pipelines.py文件編寫如下:

技術分享圖片
import pymysql
import redis
class MyspiderPipeline(object):
    fp = None
    def open_spider(self,spider):      #此方法只執行一次,在爬蟲文件開始被執行時觸發此方法
        print("開始爬蟲...")
        self.fp = open(./info.txt,w,encoding=utf-8)
    def process_item(self, item, spider):
        print("打印item",item)
        self.fp.write(item["name"]+:+item["title"]+:+item["info"]+\n)
        return item      #return的作用是將item交由下一個管道進行相應方式的存儲
    def close_spider(self,spider):    #此方法只執行一次,在爬蟲文件執行結束時觸發此方法
        print(結束爬蟲...)
        self.fp.close()

#將爬蟲數據存儲在mtsql數據庫中
class MysqlPipeline(object):
    conn = None
    cursor = None
    def open_spider(self,spider):
        self.conn = pymysql.Connect(host="127.0.0.1",port=3306,user="root",password="12345",db="scrapy",charset="utf8")
    def process_item(self,item,spider):
        self.cursor = self.conn.cursor()
        try:
            sql = "insert into teachers(name,title,info) values (%s,%s,%s)"
            self.cursor.execute(sql,[item["name"],item["title"],item["info"]])
            self.conn.commit()
            return item
        except Exception as e:
            self.conn.rollback()
    def close_spider(self,spider):
        self.conn.close()
        self.cursor.close()

# 將爬蟲文件緩存在redis數據庫中
class RedisPipeline(object):
    conn = None
    def open_spider(self, spider):
        pool = redis.ConnectionPool(host=127.0.0.1,port=6379,db=5)
        self.conn = redis.Redis(connection_pool=pool)
    def process_item(self,item,spider):
        self.conn.lpush(teachersInfo,item)
        return item
pipelines.py

利用管道進行存儲時,註意不要忘了對settings.py文件進行相應的配置

技術分享圖片
ITEM_PIPELINES = {
   mySpider.pipelines.MyspiderPipeline: 300,    #數字越小,優先級越高
   mySpider.pipelines.MysqlPipeline: 301,
   mySpider.pipelines.RedisPipeline: 302,
}
settings.py

Scrapy 框架入門簡介