From 88434eed6c46b34944c576196239358db3424fce Mon Sep 17 00:00:00 2001 From: giteeyunyunyun <18883994582@163.com> Date: Mon, 15 Mar 2021 16:01:12 +0800 Subject: [PATCH] 11-3zuoye --- ...s\345\237\272\347\241\200-11-3noteyun .md" | 350 ++++++++++++++++++ ...4\273\266\345\217\212debug-11-1noteyun.md" | 235 ++++++++++++ 2 files changed, 585 insertions(+) create mode 100644 "\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/5\347\217\255/5\347\217\255_\344\272\221/week_11/Redis\345\237\272\347\241\200-11-3noteyun .md" create mode 100644 "\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/5\347\217\255/5\347\217\255_\344\272\221/week_11/Scrapy\344\270\255\351\227\264\344\273\266\345\217\212debug-11-1noteyun.md" diff --git "a/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/5\347\217\255/5\347\217\255_\344\272\221/week_11/Redis\345\237\272\347\241\200-11-3noteyun .md" "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/5\347\217\255/5\347\217\255_\344\272\221/week_11/Redis\345\237\272\347\241\200-11-3noteyun .md" new file mode 100644 index 00000000..898e57ad --- /dev/null +++ "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/5\347\217\255/5\347\217\255_\344\272\221/week_11/Redis\345\237\272\347\241\200-11-3noteyun .md" @@ -0,0 +1,350 @@ +11-3noteyun- + +# redis简单介绍 + +https://redis.io/ + +``` +https://redis.io/ +``` + +- 什么是redis? + + `remote dictionary server`, 远程字典服务. 顾名思义, redis的基础存储方式是键对值, 是一种常用的非关系型数据库. + +- redis的特点 + + - 内存操作, 相对于传统数据库从硬盘上读取数据速度, 快了一个数量级. + + - redis服务是**单线程工作模式**, 不会产生一般的并发问题. + + 在我们使用多线程或者多进程去进行一般IO操作会发生读写冲突. 如果我们的多线程和多进程程序去读取redis消息队列当中的值时, 由于redis是单线程工作模式, 读事件和写事件都会按顺序执行, 避免了并发问题. + + ``` + 命令行中: + redis-server启动 + desktop链接 + + ``` + + + +# redis的安装 + +- 服务端 + + - windows + + ``` + https://github.com/microsoftarchive/redis + ``` + + - ubuntu + + ``` + apt-get install redis-server + ``` + + - mac + + ``` + brew install redis + ``` + +- 客户端 + + - windows + + - redis-desktop + + - ubuntu + + ``` + # 没有图形界面 + apt-get install redis-cli + ``` + + - mac + + ``` + medis + ``` + + - python连接 + + ``` + pip install redis + ``` + + ``` + import redis + + # 指定使用的database + redis_con = redis.Redis(host='localhost', port=6379, db=2)#localhost是域名 + redis_con = redis.Redis(host='127.0.0.1', port=6379, db=2)#域名绑定--的ip + + ``` + +# 启动使用 + +``` +redis-service +redis-cli -h localhost -p 6379 +select 2 + +``` + + + +# redis的数据类型和CRUD + +``` +通过redis-cli命名进行连接 + +redis-cli -h localhost -p 6379 + +# 选择使用的数据库 +C:\Users\TuNan>redis-cli +127.0.0.1:6379> select 2 +OK +127.0.0.1:6379[2]> + +# 查看当前库下所有的key +127.0.0.1:6379[2]> keys * +``` + +## String + +- Create + + ``` + set key value + ``` + +- Retrieve + + ``` + get key + ``` + +- Update + + ``` + set key value + ``` + +- Delete + + ``` + del key + ``` + +## Hash + +- Create + + ``` + hset 变量名 key value + ``` + +- Retrieve + + ``` + hget 变量名 key + ``` + +- Update + + ``` + hset 变量名 key value + ``` + +- Delete + + ``` + hdel 变量名 key + ``` + +## List + +- Create + + ``` + lpush 变量名 value + ``` + +- Retrieve + + - 通过索引取值 + + ``` + lindex 变量名 索引值 + + lindex 'list_test' 1 + ``` + + - 通过索引取一定范围的值 + + ``` + lrange 变量名 start end + + lrange 'list_test' 0 2 + ``` + +- Update + + ``` + linsert 变量名 before[after] pivot value + + linsert 'list_test' before 'a' 'b' + ``` + +- Delete + + - rpop + + 从右侧, 也就是list**的末尾移除一个元素并返回** + + ``` + rpop 'list_test' + ``` + + - lpop + + 从左侧, 也就是头部移除一个元素并返回 (先进先出) + + - lrem + + 删除一定数目的元素 + + ``` + lrem 变量名 删除个数, 删除元素 + ``` + +![image-20210315144309150](C:\Users\yunqin\AppData\Roaming\Typora\typora-user-images\image-20210315144309150.png) + +## Set + +- Create + + ``` + sadd 变量名 value + ``` + +- Retrieve + + - 获取集合中的所有成员 + + ``` + smembers 变量名 + 1) "1" + 2) "11" + 3) "1111" + 4) "1111111" + 5) "11111111" + 6) "111111111" + 127.0.0.1:6379[2]> + + ``` + + - 判断当前元素是否在集合当中 + + ``` + sismember 变量名 value + sismember 'set_test' 2 + ``` + + - 返回随机数 + + ``` + srandmember 变量名 随机返回的数量 + srandmember 'set_test' 2 + ``` + +- Update + + 无 + +- Delete + + ``` + spop 变量名 + ``` + +## Zset + +有序集合 + +> 可以通过有序集合完成一个复杂的优先级队列 + +- create + + ``` + zadd 变量名 分数 value + ``` + +- Retrieve + + - 返回当前成员数 + + ``` + zcard 'zset_test' + ``` + + - 获取一定分数区间的成员数 + + ``` + zcount 变量名 min_score max_score + ``` + + - 通过一定分数区间获取值 + + ``` + zrangebyscore 变量名 min_score max_score + + zrangebyscore 'zset_test' 2 1 + ``` + +- Update + + - 加分 + + ``` + zincrby 变量 加分值 value + + zincrby 'zset_test' 1 'b' + + zincrby z_set01 1 'q' + "11" + 127.0.0.1:6379[2]> zincrby z_set01 1 'q' + "12" + 127.0.0.1:6379[2]> + + ``` + +- Delete + + - 根据排名移除成员 + + ``` + zremrangebyrank 变量名 start stop + + zremrangebyrank 'zset_test' 1 2 + ``` + + - 根据分数移除成员 + + ``` + zremrangebyscore 变量名 min_score max_score + + zremrangebyscore 'zset_test' 2 2 + ``` + +## 课后作业 + +- 完成redis服务端和客户端的搭建 +- 练习String, List, Hash, Set的CRUD练习 +- 扩展: 练习Zset的CRUD + + + diff --git "a/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/5\347\217\255/5\347\217\255_\344\272\221/week_11/Scrapy\344\270\255\351\227\264\344\273\266\345\217\212debug-11-1noteyun.md" "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/5\347\217\255/5\347\217\255_\344\272\221/week_11/Scrapy\344\270\255\351\227\264\344\273\266\345\217\212debug-11-1noteyun.md" new file mode 100644 index 00000000..4b14e2b5 --- /dev/null +++ "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/5\347\217\255/5\347\217\255_\344\272\221/week_11/Scrapy\344\270\255\351\227\264\344\273\266\345\217\212debug-11-1noteyun.md" @@ -0,0 +1,235 @@ +10-3noteyun- + +# Scrapy的启动和debug + +- 命令行 + + ```python + scrapy crawl jd_search #在命令行中 + ``` + +- 启动脚本 + + ```python + # 新建run.py脚本 + + from scrapy import cmdline + + command = "scrapy crawl jd_search".split() + cmdline.execute(command) + ``` + +# Scrapy Item + +只是对解析的结构化结果进行一个约束, 在到达pipeline前就可以检查出数据错误. + +# Scrapy的设置 + +## 设置中间件 + +- ROBOTTEXT_OBEY + + 获取对方网站是否允许爬虫获取数据的信息. + + ``` + ROBOTTEXT_OBEY=False + ``` + + + +- 设置中间件 + + 数字越小, 离`ENGINE`越近,越先执行; + + ```python + DOWNLOADER_MIDDLEWARES = { + # 'jd_crawler_scrapy.middlewares.JdCrawlerScrapyDownloaderMiddleware': 543, + 'jd_crawler_scrapy.middlewares.UAMiddleware': 100, + } + ``` + + ![image-20210312174120669](C:\Users\yunqin\AppData\Roaming\Typora\typora-user-images\image-20210312174120669.png) + +- 设置PIPELINE + + ```python + ITEM_PIPELINES = { + 'jd_crawler_scrapy.pipelines.JdCrawlerScrapyPipeline': 300, + } + ``` + +## 请求限制 + +- 请求限制(以下几个)—— + +- CONCURRENT_REQUESTS + + concurrent_requests请求并发数,通过控制请求并发数达到避免或者延缓IP被封禁(settings里面) + + ```python +CONCURRENT_REQUESTS=1 # + ``` + +- CONCURRENT_REQUESTS_PER_DOMAIN + + 控制 每个 域名请求的并发数 + + + +- CONCURRENT_REQUESTS_IP + + 控制每个ip请求的次数。一些网站对ip封禁比较严格。 + + ```python +#CONCURRENT_REQUESTS_PER_IP = 16 + ``` + + + +- CONCURRENT_ITEMS + + 默认为100,控制处理item的并发数,如果我存入的数据库性能比较差,通过这样的方式解决防止数据库崩溃的情况。 + + + +## 延时设置 + +```python +#DOWNLOAD_DELAY = 3——设置 +#默认为0,控制请求的频率,在调度完一个请求后,休息若干秒 +#scrapy会自动帮我们进行随机休息(+-0.5s) + +#DOWNLOAD_TIMEOUT = 6——设置 +#根据自己的ip池质量自行决定,超过6s,这个ip就不要了 +#控制每个请求的超时时间,解决ip代理池质量差的问题 + +#REDIRECT_ENABLE——要关掉 +REDIRECT_ENABLE=False +#重定向 +#不加headers,会返回一个登录链接,jd商城 +#默认为true,建议修改为False,因为大部分重定向都是识别出你当前的身份有问题,重定向到login页面 + +``` + +## 过滤器 + +```python + +# settings里面:dup +DUPEFILTER_CLASS="jd_crawler_scrapy.middlewares.MyRFPDupeFilter" + +``` + +```python +#导入重试中间件#middlewares里面,过滤器的设置 +from scrapy.downloadermiddlewares.retry import RetryMiddleware +from scrapy.utils.response import response_status_message +from scrapy.dupefilters import RFPDupeFilter + +import hashlib +import weakref +from w3lib.url import canonicalize_url + +from scrapy.utils.python import to_bytes, to_unicode + +_fingerprint_cache = weakref.WeakKeyDictionary() + + +def request_fingerprint(self,request, include_headers=None, keep_fragments=False): + + cache = _fingerprint_cache.setdefault(request, {}) + cache_key = (include_headers, keep_fragments) + if cache_key not in cache: + fp = hashlib.sha1() + fp.update(to_bytes(request.method)) + fp.update(to_bytes(canonicalize_url(request.url, keep_fragments=keep_fragments))) + fp.update(request.body or b'') + fp.update(request.meta.get("batch_no","").encode("utf-8")) +``` + +```python +#jd_search里面,打开过滤器 +yield scrapy.FormRequest( + dont_filter=False,#打开过滤器 + url=url, + method="GET", + # formdata=data, #如果是post请求,携带数据,使用formdata参数 + callback=self.parse_search #指定回调函数,处理response对象 +``` + + + +## Log日志 + +- LOG 打印日志 + + - LOG_ENABLE + + 默认为`True`, 是否使用log 默认,使用log + + - LOG_FILE + + 设置保存的log文件目录 + + - LOG_LEVEL(按严重程序排序) + + - CRITICAL (critical) + - ERROR (error) + - WARNING (warning)警告 + - INFO (info)信息 + - DEBUG (debug) 打印全面的信息 + +## 重试机制 + +- RETRY_ENABLE + + 默认为true,建议改为false,然后自己重写 重试中间件 + +- RETRY_TIMES + + 控制重试次数,RETRY_TIMES其实是当前项目的兜底配置 + + 一般设置3次就行 + + - 如果当前请求失败后会永远重试,正好你请求的接口是收费的,万一有一天报错,那么产生的的费用是巨大的。 + + ```python + RETRY_TIMES=3 + ``` + +- RETRY_HTTP_CODES + +```python +# retry +RETRY_ENABLE=False +RETRY_HTTP_CODES=[500,502,503,504,408,429] +``` + +![image-20210313123648823](C:\Users\yunqin\AppData\Roaming\Typora\typora-user-images\image-20210313123648823.png) + +# Scrapy的中间件 + +- 请求头中间件 + + ```python + class UAMiddleware: + def process_request(self, request, spider): + request.headers["user-agent"] = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36" + ``` + +- 重试中间件 + + ```python + #导入重试中间件 + from scrapy.downloadermiddlewares.retry import RetryMiddleware + from scrapy.utils.response import response_status_message + ``` + + + + + +# 课后作业 + +- 将jd_crawler_scrapy完善. +- 完成代理中间件的编写(查阅文档). \ No newline at end of file -- Gitee