簡介
在使用 scrapy 爬取 IT桔子公司信息,用來進(jìn)行分析,了解 IT 創(chuàng)業(yè)公司的一切情況,之前使用 scrapy 寫了一個默認(rèn)線程是10的單個實例,為了防止被 ban IP 設(shè)置了下載的速度,3萬多個公司信息爬了1天多才完成,現(xiàn)在想到使用分布式爬蟲來提高效率。
源碼githup
技術(shù)工具:Python3.5 scrapy scrapy_redis redis docker1.12 docker-compose Kitematic mysql SQLAlchemy
準(zhǔn)備工作
安裝 Docker 點這里去了解、安裝;
pip install scrapy scrapy_redis ;
代碼編寫
分析頁面信息: 我需要獲取的是每一個「公司」的詳情頁面鏈接 和 分頁按鈕鏈接;
統(tǒng)一存儲獲取到的鏈接,提供給多個 spider 爬?。?/p>
多個 spider 共享一個 redis list 中的鏈接;
目錄結(jié)構(gòu)圖

juzi_spider.py
# coding:utf-8
from bs4 import BeautifulSoup
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from scrapy_redis.spiders import RedisCrawlSpider
from itjuzi_dis.items import CompanyItem
class ITjuziSpider(RedisCrawlSpider):
name = 'itjuzi_dis'
allowed_domains = ['']
# start_urls = ['http://www./company/157']
redis_key = 'itjuziCrawler:start_urls'
rules = [
# 獲取每一頁的鏈接
Rule(link_extractor=LinkExtractor(allow=('/company\?page=\d '))),
# 獲取每一個公司的詳情
Rule(link_extractor=LinkExtractor(allow=('/company/\d ')), callback='parse_item')
]
def parse_item(self, response):
soup = BeautifulSoup(response.body, 'lxml')
.
.省略一些處理代碼
.
return item
說明:
class 繼承了RedisCrawlSpider 而不是CrawlSpider
start_urls 改為一個自定義的 itjuziCrawler:start_urls ,這里的itjuziCrawler:start_urls 就是作為所有鏈接存儲到 redis 中的 key ,scrapy_redis 里也是通過redis 的 lpop 方法彈出并刪除鏈接的;
db_util.py
使用 SQLAlchemy 作為 ORM 工具,當(dāng)表結(jié)構(gòu)不存在時,自動創(chuàng)建表結(jié)構(gòu)
middlewares.py
增加了很多 User-Agent ,每一個請求隨機(jī)使用一個,防止防止網(wǎng)站通過 User-Agent 屏蔽爬蟲
settings.py
配置middlewares.py scrapy_redis redis 鏈接相關(guān)信息
部署
在上面的「目錄結(jié)構(gòu)圖」中有,Dockerfile 和docker-compose.yml
Dockerfile
FROM python:3.5
ENV PATH /usr/local/bin:$PATH
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
COPY spiders.py /usr/local/lib/python3.5/site-packages/scrapy_redis
CMD /usr/local/bin/scrapy crawl itjuzi_dis
說明:
使用 python3.5 作為基礎(chǔ)鏡像
將/usr/local/bin 設(shè)置環(huán)境變量
映射 host 和 container 的目錄
安裝 requirements.txt
特別要說明的是COPY spiders.py /usr/local/lib/python3.5/site-packages/scrapy_redis ,將 host 中的 spiders.py 拷貝到container 中的 scrapy_redis 安裝目錄中,因為 lpop 獲取redis 的值在 python2 中是 str 類型,而在 python3 中是 bytes 類型,這個問題在 scrapy_reids 中需要修復(fù),spiders.py 第84行需要修改;
啟動后立即執(zhí)行爬行命令 scrapy crawl itjuzi_dis
docker-compose.yml
version: '2'
services:
spider:
build: .
volumes:
- .:/code
links:
- redis
depends_on:
- redis
redis:
image: redis
ports:
- '6379:6379'
說明:
開始部署
啟動 container
docker-compose up #從 docker-compose.yml 中創(chuàng)建 `container` 們
docker-compose scale spider=4 #將 spider 這一個服務(wù)擴(kuò)展到4個,還是同一個 redis
可以在 Kitematic GUI 工具中觀察創(chuàng)建和運(yùn)行情況;

在沒有設(shè)置 start_urls 時,4個 container 中的爬蟲都處于饑渴的等待狀態(tài)

現(xiàn)在給 redis 中放入 start_urls :
lpush itjuziCrawler:start_urls http://www./company
4個爬蟲都動起來了,一直爬到start_urls 為空

以上です!ありがとうございました!
|