完整程式碼在這: 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標籤連結)
需要注意的地方
- 爬蟲部分我就不說了,我就挑特別的地方
- kafka需要bytes資料,所以在pipeline接收到資料之後一定要encode;encode裡面的encoding和消費者的decode編碼要一致.
- pipeline裡面實現一個方法 close_spider(self, spider) 用來關閉producer;不然Scrapy會一直掛在producer那裡不動.
- 我在pipeline裡面判斷了KAFKA_IP_PORT這個配置寫的引數:
- 單機部署可以用list或者str表示.
- 偽分佈或者全分佈可以用list,或者用逗號隔開都可以.
Zookeeper安裝
- 我大致說下Zookeeper的安裝過程(以下都是單點測試, 偽分佈和全分佈還請各位完整學習完後再搭建)
- 下載zookeeper.下載地址
- 解壓在conf下把zoo_sample.cfg 複製(或直接重新命名)為zoo.cfg
- 在系統環境變數中建立ZOOKEEPER_HOME值為zookeeper的Home目錄
- 在PATH中新增zookeeper的bin目錄.
- 在cmd中執行 zkServer
Kafka安裝
- 也一樣是單點
- 下載kafka並解壓.下載地址
- 進入解壓後的資料夾, 在conf下修改server.properties檔案中log.dirs指定log目錄
- 配置系統環境變數KAFKA_HOME
- 在PATH中新增kafka bin/windows的目錄(linux的不用理windows那個資料夾)
- 啟動kafka: kafka-server-start <kafka目錄下config裡面的server.properties的路徑>
- 關於kafka的測試
- 建立topic:
kafka-topics --create --topic newtest --partitions 1 --replication-factor 1 --zookeeper localhost:2181
複製程式碼
- 意思是:建立一個topic; 名字:newtest; 分割槽:1個; 副本數:1個; zookeeper的監聽地址(由於是單點且若未修改zoo.cfg, 則zookeeper預設在2181埠上執行)
- 建立producer:
kafka-console-producer --broker-list localhost:9092 --topic newtest
複製程式碼
- 此時視窗會到達等待輸入的狀態,先別關閉也不著急輸入。啟動consumer先。
- 建立consumer
kafka-console-consumer --zookeeper localhost:2181 --topic newtest
複製程式碼
- 當consumer建立成功後,回到producer的視窗輸入一些字元什麼的,看看consumer有沒有出現(注:中文有可能是亂碼,但不影響測試)
- 其他操作就請各位去參見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裡的消費者的程式碼核心功能, 主要就是接收資訊輸出到控制檯