首先,你想一下,怎样提升自己的编程能力呢? 当然是阅读优秀的代码,并且大量练习。
github 大家都不会陌生,今天我们先从github 上找一个优秀的分布式爬虫代码来阅读与学习。
首先打开github, 搜索 scrapy redis ,如图所示,找到一个星数多的,这里我取第一个,
点进去之后出现如图所示,我们要下载这些代码,下载的方式有两种,一个是点击Download Zip 下载好后直接解压出来,
今天介绍使用git 下载。
先到该网站下载自己电脑对应版本,根据提示,点击安装
这里有一点需要注意,一直选默认选项就好,不是特殊需要的话,不要随便修改,
假如这一步你选择了第一个,以后还要手动配置多个环境变量,比较麻烦,所以强烈建议一直选默认的选项。
安装完了以后,首先复制第二个图片里箭头指的那行代码,其次,在命令行cd 进你要把代码存储的文件夹,输入 git clone和你刚才复制的网址,点击确认,如图所示
(箭头所指表示下载好的文件,我下载过了,所以下载的是另一个,原理都一样)
首先,我们在Pycharm里打开刚才下载好的文件夹,可以看到,里面有很多不同格式的文件,作为学习,我们只介绍 其中 example 中的py 文件,其中example文件夹后面的几个Py 文件,在以前都介绍过,所以这次主要介绍以前没见过的文件,偶尔有的需要修改会单独提出来介绍
今天的学习方法主要是类比法,就是通过和以前学习的scrapy文件做比较,来说明分布式爬虫的不同,这样也能更加加深理解。
1 dmoz.py 文件
这个文件相当于我们以前在scrapy 中写的爬虫主文件(只是说相当于,并不是说两者的作用是相同的),可以看到前半部分和最后的parse 函数,都与以前学的相差无几。
下面这个图片是下载的该文件的源码,
这个代码是添加了说明之后的版本,为了更清晰的对比,下面代码中注释掉的汉字是对代码的解释说明,注释掉的代码是以前我们的写法,而且把url该为了红袖添香 的网址
# 链接提取器
from scrapy.linkextractors import LinkExtractor
# CrawlSpider是爬取那些具有一定规则网站的常用的爬虫,它基于Spider并有一些独特属性
from scrapy.spiders import CrawlSpider, Rule
# CrawlSpider是Spider的派生类,Spider类的设计原则是只爬取start_urls中的url
# 而CrawlSpider类定义了一些规则(rules)来提供跟进链接(link)的方便机制,从爬取的网页中获取link并继续爬取的工作更适合。
class DmozSpider(CrawlSpider):
"""Follow categories and extract links."""
name = 'dmoz'
# name = 'bole'
allowed_domains = ['hongxiu.com']
# allowed_domains = ['bole.com']
start_urls = ['https://www.hongxiu.com/finish']
# rules: 是Rule对象的集合,用于匹配目标网站并排除干扰
rules = [
# 获取网页的指定内容,然后进入到指定的方法里面
# 找到class类名为.top-cat 的标签
Rule(LinkExtractor(restrict_css=('.top-cat', '.sub-cat', '.cat-item')),
# 设置是否继续执行后面的内容
# 如果有回调函数,则默认为False ,否则为True
callback='parse_directory', follow=True),
]
# def parse(self, response):
def parse_directory(self, response):
div_list = response.xpath('//div')
for div in response.css('.title-and-desc'):
yield {
'name': div.css('.site-title::text').extract_first(),
'description': div.css('.site-descr::text').extract_first().strip(),
'link': div.css('a::attr(href)').extract_first(),
}
作对比后,可以看到首先是导入的模块不同,继承的模块也不一样。这里只多了一个rules 使用规则,将在下面介绍它的详细用法。
2 mycralwer_redis.py 文件
这个就是今天的重点内容,分布式爬虫的主文件,先看一看都有什么内容
可以到与刚才的dmoz文件很相似,但也有不同的地方,下面的代码结合着注释,来一起看看每行代码的意思
from scrapy.spiders import Rule
from scrapy.linkextractors import LinkExtractor
from scrapy_redis.spiders import RedisCrawlSpider
class MyCrawler(RedisCrawlSpider):
"""Spider that reads urls from redis queue (myspider:start_urls)."""
name = 'mycrawler_redis'
# allowed_domains = [] 这里没有allowed_domains ,start_url也没有的,
# start_urls = [''] 这个是以前的写法,这里也有,只是不在这里写。
# 类名: + start_urls 推荐写法: 标准写法
redis_key = 'mycrawler:start_urls'
rules = (
# follow all links
Rule(LinkExtractor(), callback='parse_page', follow=True),
)
# 这个里面的内容以后再详细介绍,这里知道相关单词就行
def __init__(self, *args, **kwargs):
# 动态的 定义 允许 域名 列表
# Dynamically define the allowed domains list.
# 此处动态定义域名列表
domain = kwargs.pop('domain', '')
self.allowed_domains = filter(None, domain.split(','))
# super后面写自己的类名
super(MyCrawler, self).__init__(*args, **kwargs)
def parse_page(self, response):
# 这样写是为了自己测试用
print('--------------------------')
print(response.url)
# return {
# 'name': response.css('title::text').extract_first(),
# 'url': response.url,
# }
以上就是所有说明,我们来运行试一下,首先在命令行输入redis-server redis.windows.conf 来启动redis (若是提示错误,暂时可先用redis-server 启动)
再重新进入进入一个命令行,输入redis-cli, 启动客户端,输入lpush mycrawler:start_urls https://www.hongxiu.com 点击确认(最后的网址是我自己作为测试用的,当然可以修改)
再重新进入一个新的命令行,cd 进 example 这个文件夹,输入scrapy crawl mycrawler_redis, 点击确认。
打开redis.exe文件,查看我们输入的网页,如图所示
表示运行成功。
3 myspider_redis.py 文件
首先看一下原代码
再看看注释过后的代码
from scrapy_redis.spiders import RedisSpider
class MySpider(RedisSpider):
"""Spider that reads urls from redis queue (myspider:start_urls)."""
name = 'myspider_redis'
redis_key = 'myspider:start_urls'
#
# def __init__(self, *args, **kwargs):
# # Dynamically define the allowed domains list.
# domain = kwargs.pop('domain', '')
# self.allowed_domains = filter(None, domain.split(','))
# super(MySpider, self).__init__(*args, **kwargs)
def parse(self, response):
# return {
# 'name': response.css('title::text').extract_first(),
# 'url': response.url,
# }
print('----------------')
print(response.url)
这个和mycrawler_redis文件差不多,后面的命令行输入都差不多,不过多介绍
至于两者有什么区别,以后再写。
4 setting.py 文件
先看原文件:
下来对以后可能要用到的进行说明
# Scrapy settings for example project
#
# For simplicity, this file contains only the most important settings by
# default. All the other settings are documented here:
#
# http://doc.scrapy.org/topics/settings.html
#
SPIDER_MODULES = ['example.spiders']
NEWSPIDER_MODULE = 'example.spiders'
USER_AGENT = 'scrapy-redis (+https://github.com/rolando/scrapy-redis)'
# 使用scrapy-redis 的去重类,不使用scrapy 默认的去重类
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrpyu-redis 的调度器,不使用scrapy 默认的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 控制爬虫是否允许暂停
SCHEDULER_PERSIST = True
# 队列形式,先进先出
# 那个请求先放入到请求队列里面, 那个请求就先执行
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"
# 栈形式 ,先进后出
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack"
ITEM_PIPELINES = {
'example.pipelines.ExamplePipeline': 300,
# 使用redis 数据库所要添加的管道,
# 如果使用redis数据库,必须添加
'scrapy_redis.pipelines.RedisPipeline': 400,
}
# log 日志,level 等级
# debug 调试
# LOG_LEVEL = 'DEBUG'
# 域名为字符串,如果不写,默认为本机
# 数据库的ip
REDIS_HOST = '127.0.0.1'
# 端口为数字
REDIS_PORT = 6379
# Introduce an artifical delay to make use of parallelism. to speed up the
# crawl.
# 限制爬虫速度
# DOWNLOAD_DELAY = 1
下面用一个例子过一遍整体流程.
我们中国红娘网为例,爬取特定人的姓名,年龄等,
(这里虽然说是分布式爬虫,但并不是真正的分布式,顶多算是单机的分布式爬虫)
1命令行cd 进你要创建爬虫的文件夹,输入:scrpy startproject hongniang ,然后cd hongniang
2 这里需要注意,因为要创建分布式爬虫,所以这里的命令是
# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from ..items import HongniangItem
from scrapy_redis.spiders import RedisCrawlSpider
class HongSpider(RedisCrawlSpider):
name = 'hong'
allowed_domains = ['hongniang.com']
start_urls = ['http://hongniang.com/']
redis_key = 'hongspider:start_urls'
# 特定人的url
page_link = LinkExtractor(allow=r'http://www.hongniang.com/index/search?sort=0&wh=0&sex=2&starage=1'
r'&province=%E6%B2%B3%E5%8D%97&city=%E9%83%91%E5%B7%9E&page=1')
# 取每个人的详细地址
person_link = LinkExtractor(allow=r'http://www.hongniang.com/user/member/id/\d+')
rules = (
# Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
# 这个逗号是必须加的,哪怕只有一个Rule,也要加。
Rule(page_link, True),
Rule(person_link, callback='parse_item', follow=False)
# follow 源码
# if follow is None:
# self.follow = False if callback else True
# else:
# self.follow = follow
)
def parse_item(self, response):
# i = {}
# #i['domain_id'] = response.xpath('//input[@id="sid"]/@value').extract()
# #i['name'] = response.xpath('//div[@id="name"]').extract()
# #i['description'] = response.xpath('//div[@id="description"]').extract()
# return i
header = response.xpath('//img[@id="pic_"]/@src').get()
name = response.xpath('//div[@class="name nickname"]/text()').get()
age = response.xpath('//div[@class="info2"]//ul[1]/li[1]/text()').get()
height = response.xpath('//div[@class="info2"]//ul[2]/li[1]/text()').get()
item = HongniangItem()
item['name'] = name
item['age'] = age
item['header'] = header
item['height'] = height
yield item
4 在items.py 进行相关配置,在setting.py 进行配置,把上面介绍过的setting里面example 改成这里文件夹的名字就行。
5 最关键的三步:
5.1 终端命令行 输入 redis-server 启动redis
5.2 重新打开终端命令行先cd进爬虫文件,输入 scrapy crawl hong 会看到下图,表示等待的状态
5.3 重新打开一个终端命令行: 输入 redis-cli 启动客户端,点击确认,再输入:lpush hongspider:start_urls http://www.hongniang.com 点击确认
5.4 打开redis.exe 文件,看到如图所示表示成功
(2和3的顺序也可以互换)
至此,一个简单的“分布式爬虫”就算完成了,以后我将接受如何在多台电脑上使用分布式爬虫