版权声明:本文为博主原创文章,未经博主允许不得转载。 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后就会持续不断的爬取。