Python爬虫scrapy-redis分布式实例(一)
目标任务:将之前新浪网的Scrapy爬虫项目,修改为基于RedisSpider类的scrapy-redis分布式爬虫项目,将数据存入redis数据库。
一、item文件,和之前项目一样不需要改变
# -*- coding: utf-8 -*- import scrapy
import sys
reload(sys)
sys.setdefaultencoding("utf-8") class SinanewsItem(scrapy.Item):
# 大类的标题和url
parentTitle = scrapy.Field()
parentUrls = scrapy.Field() # 小类的标题和子url
subTitle = scrapy.Field()
subUrls = scrapy.Field() # 小类目录存储路径
subFilename = scrapy.Field() # 小类下的子链接
sonUrls = scrapy.Field() # 文章标题和内容
head = scrapy.Field()
content = scrapy.Field()
二、spiders爬虫文件,使用RedisSpider类替换之前的Spider类,其余地方做些许改动即可,具体代码如下:
# -*- coding: utf-8 -*- import scrapy
import os
from sinaNews.items import SinanewsItem
from scrapy_redis.spiders import RedisSpider
import sys
reload(sys)
sys.setdefaultencoding("utf-8") class SinaSpider(RedisSpider):
name = "sina"
# 启动爬虫的命令
redis_key = "sinaspider:strat_urls"
# 动态定义爬虫爬取域范围
def __init__(self, *args, **kwargs):
domain = kwargs.pop('domain', '')
self.allowed_domains = filter(None, domain.split(','))
super(SinaSpider, self).__init__(*args, **kwargs) def parse(self, response):
items= []
# 所有大类的url 和 标题
parentUrls = response.xpath('//div[@id="tab01"]/div/h3/a/@href').extract()
parentTitle = response.xpath('//div[@id="tab01"]/div/h3/a/text()').extract() # 所有小类的ur 和 标题
subUrls = response.xpath('//div[@id="tab01"]/div/ul/li/a/@href').extract()
subTitle = response.xpath('//div[@id="tab01"]/div/ul/li/a/text()').extract() #爬取所有大类
for i in range(0, len(parentTitle)): # 爬取所有小类
for j in range(0, len(subUrls)):
item = SinanewsItem() # 保存大类的title和urls
item['parentTitle'] = parentTitle[i]
item['parentUrls'] = parentUrls[i] # 检查小类的url是否以同类别大类url开头,如果是返回True (sports.sina.com.cn 和 sports.sina.com.cn/nba)
if_belong = subUrls[j].startswith(item['parentUrls']) # 如果属于本大类,将存储目录放在本大类目录下
if(if_belong): # 存储 小类url、title和filename字段数据
item['subUrls'] = subUrls[j]
item['subTitle'] =subTitle[j]
items.append(item) #发送每个小类url的Request请求,得到Response连同包含meta数据 一同交给回调函数 second_parse 方法处理
for item in items:
yield scrapy.Request( url = item['subUrls'], meta={'meta_1': item}, callback=self.second_parse) #对于返回的小类的url,再进行递归请求
def second_parse(self, response):
# 提取每次Response的meta数据
meta_1= response.meta['meta_1'] # 取出小类里所有子链接
sonUrls = response.xpath('//a/@href').extract() items= []
for i in range(0, len(sonUrls)):
# 检查每个链接是否以大类url开头、以.shtml结尾,如果是返回True
if_belong = sonUrls[i].endswith('.shtml') and sonUrls[i].startswith(meta_1['parentUrls']) # 如果属于本大类,获取字段值放在同一个item下便于传输
if(if_belong):
item = SinanewsItem()
item['parentTitle'] =meta_1['parentTitle']
item['parentUrls'] =meta_1['parentUrls']
item['subUrls'] = meta_1['subUrls']
item['subTitle'] = meta_1['subTitle']
item['sonUrls'] = sonUrls[i]
items.append(item) #发送每个小类下子链接url的Request请求,得到Response后连同包含meta数据 一同交给回调函数 detail_parse 方法处理
for item in items:
yield scrapy.Request(url=item['sonUrls'], meta={'meta_2':item}, callback = self.detail_parse) # 数据解析方法,获取文章标题和内容
def detail_parse(self, response):
item = response.meta['meta_2']
content = ""
head = response.xpath('//h1[@id="main_title"]/text()')
content_list = response.xpath('//div[@id="artibody"]/p/text()').extract() # 将p标签里的文本内容合并到一起
for content_one in content_list:
content += content_one item['head']= head[0] if len(head) > 0 else "NULL"
item['content']= content yield item
三、settings文件设置
SPIDER_MODULES = ['sinaNews.spiders']
NEWSPIDER_MODULE = 'sinaNews.spiders' # 使用scrapy-redis里的去重组件,不使用scrapy默认的去重方式
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy-redis里的调度器组件,不使用默认的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 允许暂停,redis请求记录不丢失
SCHEDULER_PERSIST = True
# 默认的scrapy-redis请求队列形式(按优先级)
SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"
# 队列形式,请求先进先出
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"
# 栈形式,请求先进后出
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack" # 只是将数据放到redis数据库,不需要写pipelines文件
ITEM_PIPELINES = {
# 'Sina.pipelines.SinaPipeline': 300,
'scrapy_redis.pipelines.RedisPipeline': 400,
} # LOG_LEVEL = 'DEBUG' # Introduce an artifical delay to make use of parallelism. to speed up the
# crawl.
DOWNLOAD_DELAY = 1
# 指定数据库的主机IP
REDIS_HOST = "192.168.13.26"
# 指定数据库的端口号
REDIS_PORT = 6379
执行命令:
本次直接使用本地的redis数据库,将settings文件中的REDIS_HOST和REDIS_PORT注释掉。
启动爬虫程序
scrapy runspider sina.py
执行程序后终端窗口显示如下:
表示程序处于等待状态,此时在redis数据库端执行如下命令:
redis-cli> lpush sinaspider:start_urls http://news.sina.com.cn/guide/
http://news.sina.com.cn/guide/为起始url,此时程序开始执行。
Python爬虫scrapy-redis分布式实例(一)的更多相关文章
- 爬虫--scrapy+redis分布式爬取58同城北京全站租房数据
作业需求: 1.基于Spider或者CrawlSpider进行租房信息的爬取 2.本机搭建分布式环境对租房信息进行爬取 3.搭建多台机器的分布式环境,多台机器同时进行租房数据爬取 建议:用Pychar ...
- python爬虫Scrapy(一)-我爬了boss数据
一.概述 学习python有一段时间了,最近了解了下Python的入门爬虫框架Scrapy,参考了文章Python爬虫框架Scrapy入门.本篇文章属于初学经验记录,比较简单,适合刚学习爬虫的小伙伴. ...
- python爬虫项目(scrapy-redis分布式爬取房天下租房信息)
python爬虫scrapy项目(二) 爬取目标:房天下全国租房信息网站(起始url:http://zu.fang.com/cities.aspx) 爬取内容:城市:名字:出租方式:价格:户型:面积: ...
- python爬虫scrapy框架——人工识别登录知乎倒立文字验证码和数字英文验证码(2)
操作环境:python3 在上一文中python爬虫scrapy框架--人工识别知乎登录知乎倒立文字验证码和数字英文验证码(1)我们已经介绍了用Requests库来登录知乎,本文如果看不懂可以先看之前 ...
- python爬虫scrapy项目详解(关注、持续更新)
python爬虫scrapy项目(一) 爬取目标:腾讯招聘网站(起始url:https://hr.tencent.com/position.php?keywords=&tid=0&st ...
- Python爬虫Scrapy框架入门(0)
想学习爬虫,又想了解python语言,有个python高手推荐我看看scrapy. scrapy是一个python爬虫框架,据说很灵活,网上介绍该框架的信息很多,此处不再赘述.专心记录我自己遇到的问题 ...
- Python爬虫教程-新浪微博分布式爬虫分享
爬虫功能: 此项目实现将单机的新浪微博爬虫重构成分布式爬虫. Master机只管任务调度,不管爬数据:Slaver机只管将Request抛给Master机,需要Request的时候再从Master机拿 ...
- [Python爬虫] scrapy爬虫系列 <一>.安装及入门介绍
前面介绍了很多Selenium基于自动测试的Python爬虫程序,主要利用它的xpath语句,通过分析网页DOM树结构进行爬取内容,同时可以结合Phantomjs模拟浏览器进行鼠标或键盘操作.但是,更 ...
- 安装python爬虫scrapy踩过的那些坑和编程外的思考
这些天应朋友的要求抓取某个论坛帖子的信息,网上搜索了一下开源的爬虫资料,看了许多对于开源爬虫的比较发现开源爬虫scrapy比较好用.但是以前一直用的java和php,对python不熟悉,于是花一天时 ...
- Python 爬虫-Scrapy爬虫框架
2017-07-29 17:50:29 Scrapy是一个快速功能强大的网络爬虫框架. Scrapy不是一个函数功能库,而是一个爬虫框架.爬虫框架是实现爬虫功能的一个软件结构和功能组件集合.爬虫框架是 ...
随机推荐
- PID控制器的应用:控制网络爬虫抓取速度
一.初识PID控制器 冬天乡下人喜欢烤火取暖,常见的情形就是四人围着麻将桌,桌底放一盆碳火.有人觉得火不够大,那加点木炭吧,还不够,再加点.片刻之后,又觉得火太大,脚都快被烤熟了,那就取出一些木碳…… ...
- js中的var
vars变量预解析 JavaScript中,你可以在函数的任何位置声明多个var语句,并且它们就好像是在函数顶部声明一样发挥作用,这种行为称为 hoisting(悬置/置顶解析/预解析).当你使用了一 ...
- linux配置java环境
第一步: vim /etc/profile 第二步:添加以下4行 第三步:使配置生效 source /etc/profile 结束配置
- ChemDraw教程之怎么连接ChemDraw结构
将两个独立的ChemDraw结构连接到一起是使用者学习操作ChemDraw绘制窗口内容的基本能力之一.为了进一步了解ChemDraw软件,本教程将具体为您介绍怎么连接ChemDraw结构. 一.化学结 ...
- VC++ : GetIDsOfNames 调用失败,获取的dispid为-1
今天调试自己的程序,需要调用一个COM组件中的方法,利用GetIDsOfNames获取调用函数对象的DISPID. GetIDsOfNames: 把COM接口的方法名字和参数(可选)映射成一组DISP ...
- POJ 1141 Brackets Sequence(区间DP, DP打印路径)
Description We give the following inductive definition of a “regular brackets” sequence: the empty s ...
- python3.0与python2.0有哪些不同
python3的语法跟python2哪里变了. 1. python3中1/2终于等于0.5 了 2. print "Hello World"变成了print("Hello ...
- rpm源码安装mysql
1)访问官网(mysql社区服务器) http://downloads.mysql.com/archives/community/ 2)选择自己需要的版本和对应服务器(例如 服务器是centos 6. ...
- 在linux本地下载ftp中的文件
使用wget命令 -r :会在当前目录下生成192.168.30.14文件名 下面的命令就是下载这个ftp目录"/home/ftp/*"下面的所有文件 wget -r ftp:// ...
- C# EMS Client
从 C# 客户端连接 Tibco EMS 下面例子简要介绍 C# 客户端怎样使用 TIBCO.EMS.dll 来连接 EMS 服务器. using System; using System.Diagn ...