简介
在使用 scrapy 爬取 IT桔子公司信息,用来进行分析,了解 IT 创业公司的一切情况,之前使用 scrapy 写了一个默认线程是10的单个实例,为了防止被 ban IP 设置了下载的速度,3万多个公司信息爬了1天多才完成,现在想到使用分布式爬虫来提高效率。
技术工具:Python3.5 scrapy scrapy_redis redis docker1.12 docker-compose Kitematic mysql SQLAlchemy
准备工作
安装
Docker点这里去了解、安装;pip install scrapy scrapy_redis;
代码编写
分析页面信息:
我需要获取的是每一个「公司」的详情页面链接 和 分页按钮链接;统一存储获取到的链接,提供给多个
spider爬取;多个
spider共享一个redislist中的链接;
目录结构图
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 = ['itjuzi.com']
# start_urls = ['http://www.itjuzi.com/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而不是CrawlSpiderstart_urls改为一个自定义的itjuziCrawler:start_urls,这里的itjuziCrawler:start_urls就是作为所有链接存储到redis中的key,scrapy_redis里也是通过redis的lpop方法弹出并删除链接的;
db_util.py
使用 SQLAlchemy 作为 ORM 工具,当表结构不存在时,自动创建表结构
middlewares.py
增加了很多 User-Agent,每一个请求随机使用一个,防止防止网站通过 User-Agent 屏蔽爬虫
settings.py
配置middlewares.py scrapy_redis redis 链接相关信息
部署
在上面的「目录结构图」中有,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作为基础镜像将
/usr/local/bin设置环境变量映射
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中需要修复,spiders.py第84行需要修改;启动后立即执行爬行命令
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"
说明:
使用第2版本的
compose描述语言定义了
spider和redis两个servicespider默认使用当前目录的Dockerfile来创建,redis使用redis:latest镜像创建,并都映射6379端口
开始部署
启动 container
docker-compose up #从 docker-compose.yml 中创建 `container` 们
docker-compose scale spider=4 #将 spider 这一个服务扩展到4个,还是同一个 redis
可以在 Kitematic GUI 工具中观察创建和运行情况;
在没有设置 start_urls 时,4个 container 中的爬虫都处于饥渴的等待状态
现在给 redis 中放入 start_urls:
lpush itjuziCrawler:start_urls http://www.itjuzi.com/company
4个爬虫都动起来了,一直爬到start_urls为空
以上です!ありがとうございました!