上一章Python分布式爬虫详解(一)简单的介绍了什么是分布式爬虫,废话不多说,本章开始从零搭建一个爬取电影天堂电影信息的分布式爬虫。

本章知识点:

a.CrawlSpider爬取电影天堂动作片第一页数据

b.将项目改为RedisCrawlSpider爬虫

一、CrawlSpider爬虫

要想搭建分布式爬虫,我们可以写一个普通的爬虫,然后对其修改,使之成为分布式爬虫。

首先,新建CrawlSpider项目:

scrapy genspider -t crawl dytt_slaver dy2018.com

1、定义爬取字段

import scrapyclass DyttRedisSlaverItem(scrapy.Item):# 译名name = scrapy.Field()# 年代year = scrapy.Field()# 语言language = scrapy.Field()# 上映日期release_date = scrapy.Field()# 评分score = scrapy.Field()# 文件大小file_size = scrapy.Field()# 片长film_time = scrapy.Field()# 简介introduction = scrapy.Field()# 海报posters = scrapy.Field()# 下载链接download_link = scrapy.Field()

2、定义Rule规则

查看网页源码发现,电影链接为/i/[一串数字].html的形式,但是我们只需要类目中的电影而不需要推荐的电影:

所以:

movie_links = LinkExtractor(allow=r'/i/\d*.html', restrict_xpaths=('//div[@class="co_content8"]'))rules = (Rule(movie_links, callback='parse_item'),)

3、定义提取影片信息规则

观察网页源码,发现页面结构并不是统一的:

有的信息在p标签中包裹,但是也有一些信息在div标签中。而且,由于主演人数不同,标签个数也不确定。所以,用xpath进行提取不是那么的方便了。这种情况就需要选用正则表达式来进行筛选。

观察网页编码,为gb2312

有些小众的电影并没有评分。

所以,筛选规则为:

        str_resp = response.body.decode('gb2312', errors='ignore')rep_chars = ['&nbsp;', '&middot;', '&ldquo;', '&rdquo;', '&hellip;']for rep in rep_chars:str_resp = str_resp.replace(rep, '')title = re.search(r'◎片  名(.*?)</.+>', str_resp).group(1).replace(u'\u3000', '')translation = re.search(r'◎译  名(.*?)</.+>', str_resp).group(1).replace(u'\u3000', '')# 名字items['name'] = title + "|" + translation# 年代items['year'] = re.search(r'◎年  代(.*?)</.+>', str_resp).group(1).replace(u'\u3000', '')# 评分try:items['score'] = response.xpath("//strong[@class='rank']/text()").extract()[0].replace(u'\u3000', '')except:items['score'] = '无评分'# 语言items['language'] = re.search(r'◎语  言(.*?)</.+>', str_resp).group(1).replace(u'\u3000', '')# 上映日期items['release_date'] = re.search(r'◎上映日期(.*?)</.+>', str_resp).group(1).replace(u'\u3000', '')# 文件大小items['file_size'] = re.search(r'◎文件大小(.*?)</.+>', str_resp).group(1).replace(u'\u3000', '')# 片长items['film_time'] = re.search(r'◎片  长(.*?)</.+>', str_resp).group(1).replace(u'\u3000', '')# 简介items['introduction'] = re.search(r'◎简  介</.+>\r\n<.+>(.*?)</.+>', str_resp).group(1).replace(u'\u3000', '')# 海报items['posters'] = response.xpath("//div[@id='Zoom']/*[1]/img/@src").extract()[0]

经测试发现,网站的迅雷下载链接是用js动态生成的。这就要用到selenium了。

from selenium import webdriver# 下载链接
items['download_link'] = self.get_download_link(response.url)def get_download_link(self, url):chrome_options = webdriver.ChromeOptions()chrome_options.add_argument('--headless')chrome_options.add_argument('--disable-gpu')driver = webdriver.Chrome(chrome_options=chrome_options)driver.get(url)link = re.search(r'\"(thunder:.*?)\"',  driver.page_source).group(1)driver.close()return link

最后,pipelines中保存数据:

class DyttRedisSlaverPipeline(object):def __init__(self):self.file = open('movie.json', 'w')def process_item(self, item, spider):content = json.dumps(dict(item), ensure_ascii=False) + "\n"self.file.write(content)return itemdef close_spider(self, spider):self.file.close()

运行爬虫,得到第一页的30条数据:

二、修改项目为RedisCrawlSpider爬虫

1、首先修改爬虫文件

① RedisCrawlSpider修改很简单,首先需要引入RedisCrawlSpider:

from scrapy_redis.spiders import RedisCrawlSpider

② 将父类中继承的CrawlSpider改为继承RedisCrawlSpider

class DyttSlaverSpider(RedisCrawlSpider):

③ 因为slaver端要从redis数据库中获取爬取的链接信息,所以去掉allowed_domains() 和 start_urls,并添加redis_key

redis_key = 'dytt:start_urls'

④ 增加__init__()方法,动态获取allowed_domains(),[理论上要加这个,但是实测加了爬取的时候链接都被过滤了,所以我没加,暂时没发现有什么影响]

     def __init__(self, *args, **kwargs):domain = kwargs.pop('domain', '')self.allowed_domains = filter(None, domain.split(','))super(DyttSlaverSpider, self).__init__(*args, **kwargs)

2、修改setting文件

① 首先要指定redis数据库的连接参数:

REDIS_HOST = '192.168.0.131'
REDIS_PORT = 6379

② 指定使用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 queues

SCHEDULER_PERSIST = True

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

DUPEFILTER_DEBUG =True

⑦ 配置RedisPipelineitem写入key为 spider.name : items 的redis的list中,供后面的分布式处理item

ITEM_PIPELINES = {'dytt_redis_slaver.pipelines.DyttRedisSlaverPipeline': 300,'scrapy_redis.pipelines.RedisPipeline': 400
}

3、增加爬虫信息字段(可选)

由于会有多个slaver端,所以可加一个爬虫名字的字段和时间字段来区分是哪个爬虫在什么时间爬到的信息。

① item中增加字段

    # utc时间crawled = scrapy.Field()# 爬虫名spider = scrapy.Field()

② pipelines中新增类:

class InfoPipeline(object):def process_item(self, item, spider):#utcnow() 是获取UTC时间item["crawled"] = datetime.utcnow()# 爬虫名item["spider"] = spider.namereturn item

③ setting中设置ITEM_PIPELINES

ITEM_PIPELINES = {'dytt_redis_slaver.pipelines.DyttRedisSlaverPipeline': 300,'dytt_redis_slaver.pipelines.InfoPipeline':350,'scrapy_redis.pipelines.RedisPipeline': 400
}

至此,项目修改完毕,现在可以爬取某一分类下的第一页的电影信息。

以Windows10为slaver端运行一下:

因为请求队列为空,所以爬虫会停下来进行监听,直到我们在Master端给它一个新的连接:

爬虫启动,开始爬取信息:

爬取完成后,项目不会结束,而是继续等待新的爬取请求的到来,爬取结果:

本章小结:

本章将一个crawlspider爬虫改为了RedisCrawlSpider爬虫,可以实现分布式爬虫,但是由于数据量较小(只有30条)所以只用了一个slaver端。并且没有去设置代理ip和user-agent,下一章中,针对上述问题,将对项目进行更深一步的修改。

项目源码:

https://github.com/ZhiqiKou/Scrapy_notes

Python分布式爬虫详解(二)相关推荐

  1. Python爬虫——Python多线程爬虫详解

    网络爬虫程序是一种 IO 密集型程序,程序中涉及了很多网络 IO 以及本地磁盘 IO 操作,这些都会消耗大量的时间,从而降低程序的执行效率,而 Python 提供的多线程能够在一定程度上提升 IO 密 ...

  2. 【Python】全局变量详解二(修改全局变量值、定义位置和代码结构、命名建议)

    全局变量是在函数外部定义的变量(没有定义在某一个函数内),所有函数内部都可以使用这个变量. 提示:全局变量是可变的,在其他开发语言中,大多是不推荐使用全局变量的,因为可变范围太大,会导致程序后期不好维 ...

  3. 爬虫入门之urllib库详解(二)

    爬虫入门之urllib库详解(二) 1 urllib模块 urllib模块是一个运用于URL的包 urllib.request用于访问和读取URLS urllib.error包括了所有urllib.r ...

  4. 用python写一个简单的爬虫_Python实现简易Web爬虫详解

    编辑推荐: 本文主要介绍了Python实现简易Web爬虫详解,希望对大家有帮助. 本文来自于脚本之家 ,由火龙果软件Alice编辑,推荐. 简介: 网络爬虫(又被称为网页蜘蛛),网络机器人,是一种按照 ...

  5. from mysql partition select_爬虫(九十九)mysql详解二

    **mysql中字段的常见类型: ** 二进制位 bit(长度) tinyint[(长度)] [有无符号unsigned] [位数低于长度时候是否填充零zerofill] 有符号表示范围-128 ~ ...

  6. Python爬虫详解:爬虫是什么,如何做爬虫?

    Python爬虫详解:爬虫是什么,如何做爬虫? 读前必看: 本篇文章为教学向文章,通俗易懂的语言难免有不合适的地方,请大佬自行退场 爬虫是什么? 去查网,你会看到这样的解释: 爬虫是一种按照一定的规则 ...

  7. 【视频教程免费领取】聚焦Python分布式爬虫必学框架Scrapy 打造搜索引擎

    领取方式 关注公众号,发送Python0407获取下载链接. 扫码关注公众号,公众号回复 Python0407 获取下载地址 目录结构 目录:/读书ReadBook [57.6G] ┣━━48G全套J ...

  8. 三十七 Python分布式爬虫打造搜索引擎Scrapy精讲—将bloomfilter(布隆过滤器)集成到scrapy-redis中...

    Python分布式爬虫打造搜索引擎Scrapy精讲-将bloomfilter(布隆过滤器)集成到scrapy-redis中,判断URL是否重复 布隆过滤器(Bloom Filter)详解 基本概念 如 ...

  9. python数值转换机_用于ETL的Python数据转换工具详解

    ETL的考虑 做 数据仓库系统,ETL是关键的一环.说大了,ETL是数据整合解决方案,说小了,就是倒数据的工具.回忆一下工作这么些年来,处理数据迁移.转换的工作倒 还真的不少.但是那些工作基本上是一次 ...

最新文章

  1. IDEA打包出现Unable to find main class
  2. R语言中的%in%操作符是干什么的?
  3. 搜索Maven的仓库
  4. 在MacOS下使用Fiddler抓包
  5. 【Day09】JavaScript 为什么要区分微任务和宏任务
  6. html5shiv主要解决IE6-8 无法识别HTML5的新标签,父节点不能包裹子元素,以及应用CSS样式...
  7. Enterprise Library访问Access数据库
  8. ASP.NET连接ACCESS数据库web.config内路径最优写法
  9. 移动端canvas_web前端开发分享-css,js移动篇
  10. Python设置Tkinter窗口屏幕居中
  11. ubuntu下安装tun模块图文详细教程
  12. 微软官方出的各种dll丢失的修复工具
  13. excel文件修复工具_Excel文件打开后出错,部分内容丢失的修复技巧
  14. 最全的女生变声教程—正太音,萝莉音,少女音,御姐音
  15. 一个DataFrame赋值的诡异报错 A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc
  16. 移动互联网需求革命:由“生理需求”到“自我实现”
  17. 关于页面访问 404的具体解决办法
  18. 解析新浪微博JSON
  19. 常用网址收藏 (zz)
  20. 写了那么多Android布局,你知道elevation属性吗

热门文章

  1. 职业生涯那些坎!你都过去了吗?
  2. STM32F4——SD卡相关操作
  3. PRIME PATH
  4. python svr回归_使用sklearn库中的SVR做回归分析
  5. Out of Distribution(OoD)检测相关方法综述
  6. 【C/C++基础】C语言标准库
  7. Datawhale task3打卡——二手车价格预测
  8. 烂泥:域中的打印机无法打印……
  9. 生产用计算机打印机管理,办公电脑及打印机是否按电子设备计提折旧?
  10. 科目二如何能顺利通过?科目二经验