Scrapy 框架入門簡介

1、Scrapy框架簡介

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

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

一般咱們能夠很簡單的經過 Scrapy 框架實現一個爬蟲,抓取指定網站的內容或圖片。redis

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

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

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

  • Downloader(下載器):負責下載Scrapy Engine(引擎)發送的全部Requests請求,並將其獲取到的Responses交還給Scrapy Engine(引擎),由引擎交給Spider來處理,json

  • Spider(爬蟲):它負責處理全部Responses,從中分析提取數據,獲取Item字段須要的數據,並將須要跟進的URL提交給引擎,再次進入Scheduler(調度器).緩存

  • Item Pipeline(管道):它負責處理Spider中獲取到的Item,並進行進行後期處理(詳細分析、過濾、存儲等)的地方。架構

  • Downloader Middlewares(下載中間件):你能夠看成是一個能夠自定義擴展下載功能的組件。app

  • Spider Middlewares(Spider中間件):你能夠理解爲是一個能夠自定擴展和操做引擎和Spider中間通訊的功能組件(好比進入Spider的Responses;和從Spider出去的Requests)框架

3、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也會從新下載。)

4、製做 Scrapy 爬蟲 一共須要5步:

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

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

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

#編寫爬蟲文件:製做爬蟲開始爬取網頁

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

5、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

6、入門案例

(一)在開始爬取以前,必須建立一個新的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",)

二、取數據,修改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
相關文章
相關標籤/搜索