Scrapy-Redis 爬取快代理免费

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haeasringnar/article/details/83240461

前面写过使用scrapy爬取快代理的免费ip
接下来使用的是基于Redis的分布式scrapy爬取快代理免费ip

1、准备好Redis

如何安装和使用Redis这里就不做介绍了,没有安装的可以参考我之前的博客。
注意:如果要在不同的机器上使用,要开启Redis的远程访问

2、创建好虚拟环境并在虚拟环境中安装好scrapy 和 scrapy-redis

pip install scrapy scrapy-redis

3、创建基础的scrapy工程

scrapy startproject kuaidaili_redis

cd kuaidaili_redis/kuaidaili_redis

# 创建普通的爬虫
scrapy genspider kuaidailispider "www.kuaidaili.com"
# 创建基于crawl spider的爬虫
scrapy genspider -t crawl kuaidailicrawlspider "www.kuaidaili.com"

4、开始改造scrapy成为scrapy-redis

(1)、修改settings.py
# -*- coding: utf-8 -*-
BOT_NAME = 'kuaidaili_redis'

SPIDER_MODULES = ['kuaidaili_redis.spiders']
NEWSPIDER_MODULE = 'kuaidaili_redis.spiders'

# 配置UA
USER_AGENT = 'Mozilla/5.0(Macintosh;IntelMacOSX10.6;rv:2.0.1)Gecko/20100101Firefox/4.0.1'


# Obey robots.txt rules
# 是否遵循爬取规则,自己写的不需要遵循
ROBOTSTXT_OBEY = False

# 指定使用scrapy-redis的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"

# 指定使用scrapy-redis的去重
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"


# 指定排序爬取地址时使用的队列,
# 默认的 按优先级排序(Scrapy默认),由sorted set实现的一种非FIFO、LIFO方式。
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.SpiderPriorityQueue'
# 可选的 按先进先出排序(FIFO)
# SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.SpiderQueue'
# 可选的 按后进先出排序(LIFO)
# SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.SpiderStack'

# 在redis中保持scrapy-redis用到的各个队列,从而允许暂停和暂停后恢复,也就是不清理redis queues
SCHEDULER_PERSIST = True

# 只在使用SpiderQueue或者SpiderStack是有效的参数,指定爬虫关闭的最大间隔时间
# SCHEDULER_IDLE_BEFORE_CLOSE = 10

# 配置管道
ITEM_PIPELINES = {
    # 默认的管道
    'kuaidaili_redis.pipelines.KuaidailiRedisPipeline': 300,
    # Redis的管道
    'scrapy_redis.pipelines.RedisPipeline': 400,
}

# Introduce an artifical delay to make use of parallelism. to speed up the
# crawl. 人为延迟
DOWNLOAD_DELAY = 1

# 指定redis数据库的连接参数
# REDIS_PASS是我自己加上的redis连接密码(默认不做)
REDIS_HOST = '127.0.0.1'
REDIS_PORT = 6379
#REDIS_PASS = 'redisP@ssw0rd'


# LOG等级
LOG_LEVEL = 'DEBUG'

#默认情况下,RFPDupeFilter只记录第一个重复请求。将DUPEFILTER_DEBUG设置为True会记录所有重复的请求。
DUPEFILTER_DEBUG =True


# 存储数据库配置
DB_HOST = '127.0.0.1'
DB_PORT = 3306
DB_USER = 'root'
DB_PWD = 'root'
DB_NAME = 'kuaidaili_test'
DB_CHARSET = 'utf8'

# Disable cookies (enabled by default)
#COOKIES_ENABLED = False

# Disable Telnet Console (enabled by default)
#TELNETCONSOLE_ENABLED = False

# 配置请求头
DEFAULT_REQUEST_HEADERS = {
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
#   'Accept-Language': 'en',
}
(2)、修改items.py
# -*- coding: utf-8 -*-
import scrapy

class KuaidailiRedisItem(scrapy.Item):
    # 需要的数据现在这里制定好,因为在settings里面已近设置好了,所以可以和pipelines联系在一块处理数据
    # ip地址
    ip = scrapy.Field()
    # 端口
    port = scrapy.Field()
    # 爬取时间
    crawled = scrapy.Field()
    # 爬虫名
    spider = scrapy.Field() 
    # 来源名
    # sourec = scrapy.Field()   
(3)、修改pipelines.py
# -*- coding: utf-8 -*-
from datetime import datetime
import pymysql,json

class KuaidailiRedisPipeline(object):
    def process_item(self, item, spider):
        item["crawled"] = datetime.utcnow()
        item["spider"] = spider.name
        return item

# 存入到mysql中的管道类,这个不在settings里面开启,就不会影响整个工程的运行
class MysqlPipeline(object):
    """docstring for MysqlPipeline"""
    def __init__(self):
        settings = get_project_settings()
        self.host = settings['DB_HOST']
        self.port = settings['DB_PORT']
        self.user = settings['DB_USER']
        self.pwd = settings['DB_PWD']
        self.name = settings['DB_NAME']
        self.charset = settings['DB_CHARSET']
        # 链接数据库
        self.connect()

    def connect(self):
        self.conn = pymysql.connect(host=self.host,
                             port=self.port,
                             user=self.user,
                             password=self.pwd,
                             db=self.name,
                             charset=self.charset)
        self.cursor = self.conn.cursor()

    def close_spider(self, spider):
        self.conn.close()
        self.cursor.close()

    def process_item(self, item, spider):
        # sql = 'insert into ip_list(ip, port) values("%s", "%s")' % (item['ip'], item['port'])
        # # 执行sql语句
        # self.cursor.execute(sql)
        # # 提交之后才会生效
        # self.conn.commit()
        return item
(4)、创建你的第一个scrapy-redis的spider 命名为myredisspider.py
# myredisspider.py
from scrapy_redis.spiders import RedisSpider
from kuaidaili_redis.items import KuaidailiRedisItem


class MyRedisSpider(RedisSpider):
    """Spider that reads urls from redis queue (myspider:start_urls)."""
    name = 'myredisspider'
    # 注意这里原本应该是start_urls,但是使用redis后变成redis_key
    redis_key = 'myredisspider:start_urls'
    
	# 这里本来应该是 allowed_domains = ['www.kuaidaili.com'] ,然后变成自动捕捉的,
	#值得注意的是这里使用allowed_domains = ['www.kuaidaili.com']仍然有效
    def __init__(self, *args, **kwargs):
        # Dynamically define the allowed domains list.
        domain = kwargs.pop('domain', '')
        self.allowed_domains = filter(None, domain.split(','))
        super(MyRedisSpider, self).__init__(*args, **kwargs)

    def parse(self, response):
        print('开始爬取...')
        ip_list = response.xpath('//tbody/tr/td[1]/text()').extract()
        port_list = response.xpath('//tbody/tr/td[2]/text()').extract()
        for i in range(len(ip_list)):
            item = KuaidailiRedisItem()
            item['ip'] = ip_list[i]
            item['port'] = port_list[i]
            yield item

到这一步来,一个简单的scrapy-redis分布式爬虫已经完成了,那么来运行一下看看吧
如何运行:使用scrapy-redis后的运行方式和原本的运行方式有一定的区别

# 在你的工程目录下
scrapy runspider spiders/myredisspider.py
# myredisspider.py 是你的爬虫文件名

运行之后就会发现,scrapy爬虫会暂定在redis的地方,它会等待redis里面接受的任务时开始正真的爬取。
打开你的Redis控制端
输入一下命令:

LPUSH myredisspider:start_urls https://www.kuaidaili.com/free/intr/
# 注意这里的key  myredisspider:start_urls  就是我们在myredisspider.py里面配置的redis_key

然后你就会可以看到scrapy-redis工作起来了,可以尝试在不同的机器上运行scrapy-redis,然后在redis内输入更多的地址,观察各个分布式爬虫是否都会工作起来

(5)、创建你的第一个基于RedisCrawlSpider的spider 命名为mycrawlredisspider.py
# mycrawlredisspider.py
from scrapy.spiders import Rule
from scrapy.linkextractors import LinkExtractor
from kuaidaili_redis.items import KuaidailiRedisItem
from scrapy_redis.spiders import RedisCrawlSpider

class MyCrawlRedisSpider(RedisCrawlSpider):
    """Spider that reads urls from redis queue (myspider:start_urls)."""
    name = 'mycrawlredisspider'
    redis_key = 'mycrawlredisspider:start_urls'
    allowed_domains = ['www.kuaidaili.com']

    links = LinkExtractor(restrict_xpaths=r'//div[@id="listnav"]//a')
    rules = (
        Rule(links, callback = "parse_test",follow=True),
    )

    def parse_test(self, response):
        print('开始爬取...')
        ip_list = response.xpath('//tbody/tr/td[1]/text()').extract()
        port_list = response.xpath('//tbody/tr/td[2]/text()').extract()
        for i in range(len(ip_list)):
            item = KuaidailiRedisItem()
            item['ip'] = ip_list[i]
            item['port'] = port_list[i]
            yield item

如何运行:基于RedisCrawlSpider的spider就更简单了,它会根据我们设置的规则找到基于爬取的url持续跟进爬取。
运行方式和myredisspider.py的运行方式一样。
当如果起始url后就会持续不断的爬取。

猜你喜欢

转载自blog.csdn.net/haeasringnar/article/details/83240461
今日推荐