做为跟MongoDB一样NoSQL阵营的Redis,也具备相似的“直爽快”特性。它自己读取速度快,又提供丰富的数据结构,避免程序员重复造轮子。大名鼎鼎的分布式scrapy也是基于redis,因此赶忙了解一下呗!html
建议指定配置文件的方式启动,个人配置文件所在路径: /etc/redis/redis-server.conf
就不知道大家的是否是啦python
启动方式:redis-server /etc/redis/redis-server.conf
程序员
redis-cli
exit
redis是key-value的数据,key的类型是字符串,value类型能够是:string,hash,list,set,zsetredis
最基本类型,最大存储512M数据,可存储任何数据:数字,图片,序列化对象等数据库
set key value
mset key1 value1 key2 value2 key3 value3...
get key
;也能够一次获取多个键值:mget key1 key2 key3...
append key value
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
persist key
用于存储对象,对象格式为键值对
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命令提示也能自动弹出来,可是——
哈哈,布吉岛布吉岛,先占位之后填坑吧数据结构
列表的元素类型是string,按照插入顺序排序,可列表的头或尾添加元素多线程
lpush/rpush key value
,每次返回的值是列表中的元素个数 linsert key before/after pivot value
,这里的支点(pivot)就是原列表中的元素,value则是须要新添加的元素 lpop/rpop key
,这里能够用python的list类型的pop方法来理解 lindex key index
llen key
lset key index value
,指定元素在列表中的索引(index),value是修改后的内容。==若是index值上并不存在元素,报索引错误==lrange key startIndex stopIndex
ltrim key startIndex stopIndex
无序集合,元素类型string,元素具备惟一性,不重复app
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 有序集合,惟一性,每一个元素都会关联到一个double类型的score,表示权重,根据权重对元素排序,元素的score能够相同python爬虫
zadd key score member
;zadd key socre1 member1 score2 member2 ...
zrem key member/zrem key member1 member2 ...
zrange key start stop
zcard key
zcount key min max
zscore key member
Redis 发布订阅(pub/sub)是一种消息通讯模式:发送者(pub)发送消息,订阅者(sub)接收消息。
subscribe 频道名1 [频道名2 ...]
订阅 unsubscribe 频道名1 [频道名2 ...]
退订 message以后显示频道,再以后显示正文
publish 频道 消息
发布发布消息
接受消息
每一个主均可以设置许多的从,每一个从又能够设置许多的从;经过设置主从,搭建分布式,如scrapy-redis分布式爬虫
bind 主机Ip
bind 从机Ip
slaveof 主机Ip port
import redis
r = redis.StrictRedis(host="hostname", prot=6379)
r.set("name", "kaihui") / r.get("name")
p = r.pipeline()
p.set(...)
p.get(...)
p.execute()
以前在redis客户端操做的命令,都很好的封装到了链接数据库的对象里,能够直接使用,如:r.hset() r.sadd()…
以前抓取过电影排行榜,句子迷,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的开源项目差之千里
想起一晚趴在床上看《爱你就像爱生命》,有多少人知道王小波也是个程序员呢?他在给朋友晓阳的信中这样写道:个人图像部分也是汇编写的,反复优化,也达不到他的水平,不得不认可技不如人。
路漫漫其修远兮呢!