python爬虫有要求会redis么_Python爬虫-Redis

Python爬虫-Redis

前言

作为跟MongoDB同样NoSQL阵营的Redis,也具有类似的“直爽快”特性。它本身读取速度快,又提供丰富的数据结构,避免程序员重复造轮子。大名鼎鼎的分布式scrapy也是基于redis,所以赶紧了解一下呗!

启动服务器

建议指定配置文件的方式启动,我的配置文件所在路径: /etc/redis/redis-server.conf 就不知道你们的是不是啦

启动方式:redis-server /etc/redis/redis-server.conf

启动客户端

进入命令行:redis-cli

退出客户端:exit

数据操作

redis是key-value的数据,key的类型是字符串,value类型可以是:string,hash,list,set,zset

string

最基本类型,最大存储512M数据,可存储任何数据:数字,图片,序列化对象等

设置键值:set key value

也可以一次设置多个数据:mset key1 value1 key2 value2 key3 value3...

获取键值:get key;也可以一次获取多个键值:mget key1 key2 key3...

如果不存在,返回nil

甚至还能追加键值:append key value

也可以获取键值长度(有点像C语法哇):strlen key

也可以在设置键值的时候设置过期时间:setex key seconds value

运算(键值要求为数值):incr key 键值+1;incrby key increment 键值指定+increment ;相对应的就有decr key 键值-1,decrby key increment 指定-increment

键命令

(不仅仅针对于string类型,其他value类型的key都适用)

查找键:keys pattern(支持正则),所以查看全部键可以是keys *

查看键是否存在:exists key,存在返回1,不存在返回0

也可以一次查询多个键:exists key1 key2 ...,返回值为总和

查看键的类型:type key

删除键:del key,成功返回1,失败或键不存在返回0;或者删除多个键:del key1 key2 ...,返回值为总和,即便键不存在,亦不会报错

设置过期时间:expire key seconds;查看键的剩余存活时间:ttl key

expire操作后返回1表示设置成功,返回0表示设置失败或是键不存在,设置时间单位秒;ttl操作后返回剩余存货时间,如果返回-2表示键不存在,如果返回-1代表永久存在

当然,也能清除过期时间:persist key

如果persit操作之后返回1表示操作成功;如果返回0,键不存在或键本身就是永久

hash

用于存储对象,对象格式为键值对

1. hset key field value / hmset key field1 value1 field2 value2 ...,如何理解”对象”呢?即:一个人,这就是一个对象,有名字,年龄,性别等

2. hget key field / hmget key field1 field2 ...

3. 获取指定key的所有字段和值: hgetall key

4. 获取指定key的所有字段:hkeys key

5. 获取指定key的所有值:hvals key

6. 获取指定key的字段个数:hlen key

7. 判断key的字段是否存在:hexists key field,存在返回1,不存在返回0

8. 删除字段及对应值:hdel key field / hdel key field1 field2 ...

9. 删除key:del key

10. 获取值的字符串长度:hstrlen key field 我查了使用文档,的确存在这个hstrlen命令,用Tab命令提示也能自动弹出来,但是——

哈哈,布吉岛布吉岛,先占位以后填坑吧

list

列表的元素类型是string,按照插入顺序排序,可列表的头或尾添加元素

从头/尾部插入:lpush/rpush key value,每次返回的值是列表中的元素个数

在一个元素的前/后插入元素:linsert key before/after pivot value,这里的支点(pivot)就是原列表中的元素,value则是需要新添加的元素

失败则返回-1

移除并获得值:lpop/rpop key,这里可以用python的list类型的pop方法来理解

利用索引获取元素:lindex key index

获取key的长度(也就是列表中的元素个数):llen key

修改列表中的元素值:lset key index value,指定元素在列表中的索引(index),value是修改后的内容。==如果index值上并不存在元素,报索引错误==

返回指定范围的元素:lrange key startIndex stopIndex

超出索引范围不报错

裁剪列表:ltrim key startIndex stopIndex

set

无序集合,元素类型string,元素具有唯一性,不重复

添加元素:sadd key member;或者一次添加多个:sadd key member1 member2 ...,如果添加的元素已存在,返回0

移除元素:srem key member / srem key member1 member2 ...

获取所有元素:smembers key

获取集合元素个数:scard key

求多个集合的交集:sinter key1 key2 ...

求集合与其他集合的差集:sdiff key1 key2 ...

求多个集合的合集:sunion key1 kye2 ...

判断元素是否在集合中:sismember key member,存在返回1,不存在返回0

zset

有序集合,唯一性,每个元素都会关联到一个double类型的score,表示权重,根据权重对元素排序,元素的score可以相同

zadd key score member;zadd key socre1 member1 score2 member2 ...

zrem key member/zrem key member1 member2 ...

zrange key start stop

zcard key

统计score值在min与max的个数:zcount key min max

返回member的score值:zscore key member

发布订阅

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。

消息格式:

a. subscribe 频道名1 [频道名2 ...] 订阅

b. unsubscribe 频道名1 [频道名2 ...] 退订

c. message之后显示频道,再之后显示正文

d. publish 频道 消息 发布

发布消息

接受消息

主从配置

每个主都可以设置许多的从,每个从又可以设置许多的从;通过设置主从,搭建分布式,如scrapy-redis分布式爬虫

对主机修改配置文件:bind 主机Ip

对从机修改配置文件:

bind 从机Ip

slaveof 主机Ip port

与python交互

安装包redis,导入:import redis

连接redis:r = redis.StrictRedis(host="hostname", prot=6379)

使用方法1:根据数据类型,使用对应方法,如:r.set("name", "kaihui") / r.get("name")

使用方法2:

p = r.pipeline()

p.set(...)

p.get(...)

p.execute()

==法2缓冲多条命令,然后一次性执行,减少服务器-客户端之间TCP数据库包,从而提高效率==

之前在redis客户端操作的命令,都很好的封装到了连接数据库的对象里,可以直接使用,如:r.hset() r.sadd()…

利用redis实战

之前抓取过电影排行榜,句子迷,QQ空间,音乐热评等等,其实大多操作类似,今天想换别的方向(其实操作也类似)。

众所周知,爬虫是容易封ip的,为了应对如此强硬的反扒措施,有了利用代理ip爬取信息的方法。既然有了需求,当然就有了市场,我也没非要不可的数据需要爬取,便不至于花钱购买代理。

西刺网站提供免费代理,既然有“免费”二字,效果大家就应该心知肚明的。或许人公司提供的效果不至于那么差,却奈何全国爬虫都想“好好”利用。

分析网页一如既往,这个网页毫无难度,requests发起get请求,利用xpath解析响应,提取ip和端口号,再存入redis。稍微不同的是,我们拿到的代理ip能不能用呢?这里需要做一个测试,我写了一个filter_ip()函数进行过滤,主要思想是利用代理去访问百度,如果返回状态码是200,那么OK,存起来;否则丢弃

def filter_ip(proxyData):

# 剔除https类型的

if proxyData["type"].upper() == "HTTPS":

return

del proxyData["type"]

# 构造requests模块ip代理的参数结构

proxyData = {

"http":"http://"+proxyData["ip"]+":"+proxyData["port"]

}

try:

response = requests.get(url="http://www.baidu.com/", proxies=proxyData)

response.raise_for_status()

except:

print(f"{proxyData}不可用")

return None

# 若可用,存入redis

to_redis(proxyData)

由于构建ip池只是为了更好的辅助爬虫,所以效率方面要求严格,为此我利用了多进程+多线程来达到目的

# 设置进程池

pool = Pool(10)

for item in parse_html(html):

pool.apply_async(set_threading, (item, ))

pool.close()

pool.join()

def set_threading(item):

# 设置线程函数

t = Thread(target=filter_ip, args=(item, ))

t.start()

t.join()

整体逻辑如下

反思

我抓取了代理网页前三页,然而仅9个写入数据库,其免费可想而知

最初写的单进程+单线程,运行速度极慢,才想到多进程+多线程。多番调试,速度提升了6倍。然而也不过对300个ip处理而已,竟需要200s上下。与GitHub上最高star的开源项目差之千里

想起一晚趴在床上看《爱你就像爱生命》,有多少人知道王小波也是个程序员呢?他在给朋友晓阳的信中这样写道:我的图像部分也是汇编写的,反复优化,也达不到他的水平,不得不承认技不如人。

路漫漫其修远兮呢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值