第一个分布式爬虫项目

首先,你想一下,怎样提升自己的编程能力呢? 当然是阅读优秀的代码,并且大量练习。

一 使用git 下载github 上优秀的代码

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 这里需要注意,因为要创建分布式爬虫,所以这里的命令是

scrapy genspider -t crawl hong hongniang.com

这里写图片描述
3 进入hong.py 文件,代码见下图

# -*- 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的顺序也可以互换)

至此,一个简单的“分布式爬虫”就算完成了,以后我将接受如何在多台电脑上使用分布式爬虫

展开阅读全文

没有更多推荐了,返回首页