Scrapy Kafka的連線使用

NullSpider發表於2018-02-24

完整程式碼在這: Here

  • 以下有什麼說的不對的地方也歡迎各位指出,互相學習.

準備工作

  • Zookeeper環境(zookeeper-3.4.10) -> 具體安裝下面講 安裝步驟
  • Kafka環境(kafka-1.0.0) -> 具體安裝下面講 安裝步驟
  • 系統環境(Win10 x64)
  • Python環境(Python 3.4.4)

環境依賴

  • 環境
    • Python3.4.4(Python2暫未測試,如果有測試過的給我提下issue)
  • 依賴包
    • Scrapy
    • pykafka
  • 安裝方式:
windows: pip install requirements.txt
linux: pip3 install requiremnets.txt
複製程式碼

專案結構

  • consumer --- pykafka的消費者模組(測試接收以及之後接收爬蟲資料)
  • producer --- pykafka的生產者模組(測試傳送)
  • scrapy_kafka --- Scrapy + pykafka的爬蟲(爬的是我學校的官網的所有a標籤連結)

需要注意的地方

  • 爬蟲部分我就不說了,我就挑特別的地方
  1. kafka需要bytes資料,所以在pipeline接收到資料之後一定要encode;encode裡面的encoding和消費者的decode編碼要一致.
  2. pipeline裡面實現一個方法 close_spider(self, spider) 用來關閉producer;不然Scrapy會一直掛在producer那裡不動.
  3. 我在pipeline裡面判斷了KAFKA_IP_PORT這個配置寫的引數:
    • 單機部署可以用list或者str表示.
    • 偽分佈或者全分佈可以用list,或者用逗號隔開都可以.

Zookeeper安裝

  • 我大致說下Zookeeper的安裝過程(以下都是單點測試, 偽分佈和全分佈還請各位完整學習完後再搭建)
  1. 下載zookeeper.下載地址
  2. 解壓在conf下把zoo_sample.cfg 複製(或直接重新命名)為zoo.cfg
  3. 在系統環境變數中建立ZOOKEEPER_HOME值為zookeeper的Home目錄
  4. 在PATH中新增zookeeper的bin目錄.
  5. 在cmd中執行 zkServer

Kafka安裝

  • 也一樣是單點
  1. 下載kafka並解壓.下載地址
  2. 進入解壓後的資料夾, 在conf下修改server.properties檔案中log.dirs指定log目錄
  3. 配置系統環境變數KAFKA_HOME
  4. 在PATH中新增kafka bin/windows的目錄(linux的不用理windows那個資料夾)
  5. 啟動kafka: kafka-server-start <kafka目錄下config裡面的server.properties的路徑>
  • 關於kafka的測試
  1. 建立topic:
kafka-topics --create --topic newtest --partitions 1 --replication-factor 1 --zookeeper localhost:2181 
複製程式碼
  • 意思是:建立一個topic; 名字:newtest; 分割槽:1個; 副本數:1個; zookeeper的監聽地址(由於是單點且若未修改zoo.cfg, 則zookeeper預設在2181埠上執行)
  1. 建立producer:
kafka-console-producer --broker-list localhost:9092 --topic newtest  
複製程式碼
  • 此時視窗會到達等待輸入的狀態,先別關閉也不著急輸入。啟動consumer先。
  1. 建立consumer
kafka-console-consumer  --zookeeper localhost:2181 --topic newtest
複製程式碼
  • 當consumer建立成功後,回到producer的視窗輸入一些字元什麼的,看看consumer有沒有出現(注:中文有可能是亂碼,但不影響測試)
  1. 其他操作就請各位去參見kafka的官方文件或者系統學習後看看命令列的使用。

核心程式碼

  • 程式碼部分最好看倉庫: 程式碼倉庫地址

  • 以下是pipeline的程式碼, 主要也就是這部分和Kafka進行資料互動

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

# Scrapy
from scrapy.conf import settings

# PyKafka
from pykafka import KafkaClient


class ScrapyKafkaPipeline(object):
    def __init__(self):
        # 判斷下配置裡面個給的是啥
        # 1. 如果長度等於1, list只有一個資料, 如果是字元肯定大於1
        # 2. 否則, 判斷型別是否是list, 是的話用 逗號分隔
        # 3. 否則就是一個字串
        kafka_ip_port = settings['KAFKA_IP_PORT']
        if len(kafka_ip_port) == 1:
            kafka_ip_port = kafka_ip_port[0]
        else:
            if isinstance(kafka_ip_port, list):
                kafka_ip_port = ",".join(kafka_ip_port)
            else:
                kafka_ip_port = kafka_ip_port

        # 初始化client
        self._client = KafkaClient(hosts=kafka_ip_port)

        # 初始化Producer 需要把topic name變成位元組的形式
        self._producer = \
            self._client.topics[
                settings['KAFKA_TOPIC_NAME'].encode(encoding="UTF-8")
            ].get_producer()

    def process_item(self, item, spider):
        """
        寫資料到Kafka
        :param item:
        :param spider:
        :return:
        """
        if spider.name == "KafkaScrapy":
            self._producer.produce(item['url'].encode(encoding="UTF-8"))
            return item

    def close_spider(self, spider):
        """
        結束之後關閉Kafka
        :return:
        """
        if spider.name == "KafkaScrapy":
            self._producer.stop()


複製程式碼
  • demo裡的消費者的程式碼核心功能, 主要就是接收資訊輸出到控制檯

相關文章