Requests什么的通通爬不了的Python超强反爬虫方案!


Posted in Python onMay 20, 2021

一、前言

一个非常强的反爬虫方案 —— 禁用所有 HTTP 1.x 的请求!

现在很多爬虫库其实对 HTTP/2.0 支持得不好,比如大名鼎鼎的 Python 库 —— requests,到现在为止还只支持 HTTP/1.1,啥时候支持 HTTP/2.0 还不知道。

Scrapy 框架最新版本 2.5.0(2021.04.06 发布)加入了对 HTTP/2.0 的支持,但是官网明确提示,现在是实验性的功能,不推荐用到生产环境,原文如下:

HTTP/2 support in Scrapy is experimental, and not yet recommended for production environments. Future Scrapy versions may introduce related changes without a deprecation period or warning.

插一句,Scrapy 中怎么支持 HTTP/2.0 呢?在 settings.py 里面换一下 Download Handlers 即可:

DOWNLOAD_HANDLERS = {
    'https': 'scrapy.core.downloader.handlers.http2.H2DownloadHandler',
}

当前 Scrapy 的 HTTP/2.0 实现的已知限制包括:

  • 不支持 HTTP/2.0 明文(h2c),因为没有主流浏览器支持未加密的 HTTP/2.0。
  • 没有用于指定最大帧大小大于默认值 16384 的设置,发送更大帧的服务器的连接将失败。
  • 不支持服务器推送。
  • 不支持bytes_received和 headers_received信号。

关于其他的一些库,也不必多说了,对 HTTP/2.0 的支持也不好,目前对 HTTP/2.0 支持得还可以的有 hyper 和 httpx,后者更加简单易用一些。

二、反爬虫

所以,你想到反爬虫方案了吗?

如果我们禁用所有的 HTTP/1.x 的请求,是不是能通杀掉一大半爬虫?requests 没法用了,Scrapy 除非升级到最新版本才能勉强用个实验性版本,其他的语言也不用多说,也会杀一大部分。

而浏览器对 HTTP/2.0 的支持现在已经很好了,所以不会影响用户浏览网页的体验。

三、措施

那就让我们来吧!

这个怎么做呢?其实很简单,在 Nginx 里面配置一下就好了,主要就是加这么个判断就行了:

if ($server_protocol !~* "HTTP/2.0") {
  return 444;
}

就是这么简单,这里 $server_protocol 就是传输协议,其结果目前有三个:HTTP/1.0HTTP/1.1 和 HTTP/2.0,另外判断条件我们使用了 !~* ,意思就是不等于,这里的判断条件就是,如果不是 HTTP/2.0,那就直接返回 444 状态码,444 一般代表 CONNECTION CLOSED WITHOUT RESPONSE,就是不返回任何结果关闭连接。

我的服务是在 Kubernetes 里面运行的,所以要加这个配置还得改下 Nginx Ingress 的配置,不过还好 https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/ 预留了一个配置叫做 nginx.ingress.kubernetes.io/server-snippet,利用它我们可以自定义 Nginx 的判定逻辑。

官方用法如下:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/server-snippet: |
        set $agentflag 0;
        if ($http_user_agent ~* "(Mobile)" ){
          set $agentflag 1;
        }
        if ( $agentflag = 1 ) {
          return 301 https://m.example.com;
        }

所以这里,我们只需要改成刚才的配置就好了:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/server-snippet: |
      if ($server_protocol !~* "HTTP/2.0") {
        return 444;
      }

大功告成!

配置完成了,示例网站是:https://spa16.scrape.center/

我们在浏览器中看下效果:

Requests什么的通通爬不了的Python超强反爬虫方案!

可以看到所有请求都是走的 HTTP/2.0,页面完全正常加载。

然而,我们使用 requests 来请求一下:

import requests
response = requests.get('https://spa16.scrape.center/')
print(response.text)

非常欢乐的报错:

Traceback (most recent call last):
  ...
    raise RemoteDisconnected("Remote end closed connection without"
http.client.RemoteDisconnected: Remote end closed connection without response
 
During handling of the above exception, another exception occurred:
 
Traceback (most recent call last):
  ...
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
requests.packages.urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='spa16.scrape.center', port=443): Max retries exceeded with url: / (Caused by ProxyError('Cannot connect to proxy.', RemoteDisconnected('Remote end closed connection without response')))
 
During handling of the above exception, another exception occurred:
 
Traceback (most recent call last):
 ...
requests.exceptions.ProxyError: HTTPSConnectionPool(host='spa16.scrape.center', port=443): Max retries exceeded with url: / (Caused by ProxyError('Cannot connect to proxy.', RemoteDisconnected('Remote end closed connection without response')))

如果你用 requests,无论如何都不行的,因为它就不支持 HTTP/2.0。

那我们换一个支持 HTTP/2.0 的库呢?比如 httpx,安装方法如下:

pip3 install 'httpx[http2]'

注意,Python 版本需要在 3.6 及以上才能用 httpx。

安装好了之后测试下:

import httpx
client = httpx.Client(http2=True)
 
response = client.get('https://spa16.scrape.center/')
print(response.text)

结果如下:

<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><meta name=referrer content=no-referrer><link rel=icon href=/favicon.ico><title>Scrape | Book</title><link href=/css/chunk-50522e84.e4e1dae6.css rel=prefetch><link href=/css/chunk-f52d396c.4f574d24.css rel=prefetch><link href=/js/chunk-50522e84.6b3e24aa.js rel=prefetch><link href=/js/chunk-f52d396c.f8f41620.js rel=prefetch><link href=/css/app.ea9d802a.css rel=preload as=style><link href=/js/app.b93891e2.js rel=preload as=script><link href=/js/chunk-vendors.a02ff921.js rel=preload as=script><link href=/css/app.ea9d802a.css rel=stylesheet></head><body><noscript><strong>We're sorry but portal doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.a02ff921.js></script><script src=/js/app.b93891e2.js></script></body></html>

可以看到,HTML 就成功被我们获取到了!这就是 HTTP/2.0 的魔法!

我们如果把 http2 参数设置为 False 呢?

import httpx
client = httpx.Client(http2=False)
 
response = client.get('https://spa16.scrape.center/')
print(response.text)

一样很不幸:

Traceback (most recent call last):
 ...
    raise RemoteProtocolError(msg)
httpcore.RemoteProtocolError: Server disconnected without sending a response.
 
The above exception was the direct cause of the following exception:
  ...
    raise mapped_exc(message) from exc
httpx.RemoteProtocolError: Server disconnected without sending a response.

所以,这就印证了,只要 HTTP/1.x 通通没法治!可以给 requests 烧香了!

又一个无敌反爬虫诞生了!各大站长们,安排起来吧~

到此这篇关于Requests什么的通通爬不了的Python超强反爬虫方案!的文章就介绍到这了,更多相关Python反爬虫内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
tornado框架blog模块分析与使用
Nov 21 Python
Python编写屏幕截图程序方法
Feb 18 Python
pycharm安装图文教程
May 02 Python
python中print()函数的“,”与java中System.out.print()函数中的“+”功能详解
Nov 24 Python
python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)
Dec 20 Python
通过python+selenium3实现浏览器刷简书文章阅读量
Dec 26 Python
Python面向对象之继承和组合用法实例分析
Aug 27 Python
pygame实现贪吃蛇游戏(上)
Oct 29 Python
python 实现生成均匀分布的点
Dec 05 Python
Python爬虫库BeautifulSoup获取对象(标签)名,属性,内容,注释
Jan 25 Python
python缺失值的解决方法总结
Jun 09 Python
Python3 多线程(连接池)操作MySQL插入数据
Jun 09 Python
python使用glob检索文件的操作
python opencv通过按键采集图片源码
python 如何执行控制台命令与操作剪切板
教你怎么用Python生成九宫格照片
用 Python 元类的特性实现 ORM 框架
May 19 #Python
浅谈Python 中的复数问题
May 19 #Python
Python机器学习之基础概述
You might like
使用adodb lite解决问题
2006/12/31 PHP
免费的ip数据库淘宝IP地址库简介和PHP调用实例
2014/04/08 PHP
PHP封装分页函数实现文本分页和数字分页
2014/10/23 PHP
PHP批量查询WordPress留言者E-mail地址实现方法
2015/02/15 PHP
PHP设计模式之PHP迭代器模式讲解
2019/03/22 PHP
php实现简单四则运算器
2020/11/29 PHP
20款效果非常棒的 jQuery 插件小结分享
2011/11/18 Javascript
当json键为数字时的取值方法解析
2013/11/15 Javascript
Jquery对数组的操作技巧整理
2014/03/25 Javascript
用javascript关闭本窗口不弹出询问框的方法
2014/09/12 Javascript
JQuery中使用on方法绑定hover事件实例
2014/12/09 Javascript
JavaScript实现DIV层拖动及动态增加新层的方法
2015/05/12 Javascript
用户代理字符串userAgent可实现的四个识别
2015/09/20 Javascript
jQuery控制li上下循环滚动插件用法实例(附demo源码下载)
2016/05/28 Javascript
vue slot 在子组件中显示父组件传递的模板
2018/03/02 Javascript
基于jquery实现左右上下移动效果
2018/05/02 jQuery
微信小程序自定义导航栏
2018/12/31 Javascript
Easyui 关闭jquery-easui tab标签页前触发事件的解决方法
2019/04/28 jQuery
[38:51]2014 DOTA2国际邀请赛中国区预选赛 Orenda VS LGD-CDEC
2014/05/22 DOTA
浅谈Python爬取网页的编码处理
2016/11/04 Python
python爬虫_微信公众号推送信息爬取的实例
2017/10/23 Python
python时间日期函数与利用pandas进行时间序列处理详解
2018/03/13 Python
python的一些加密方法及python 加密模块
2019/07/11 Python
django框架基于queryset和双下划线的跨表查询操作详解
2019/12/11 Python
django在保存图像的同时压缩图像示例代码详解
2020/02/11 Python
浅谈python多线程和多线程变量共享问题介绍
2020/04/17 Python
Python DES加密实现原理及实例解析
2020/07/17 Python
python实现canny边缘检测
2020/09/14 Python
美国从事品牌鞋类零售的连锁店:Famous Footwear
2016/08/25 全球购物
英国儿童家具专卖店:GLTC
2016/09/24 全球购物
viagogo法国票务平台:演唱会、体育比赛、戏剧门票
2017/03/27 全球购物
美国珠宝精品店:Opulent Jewelers
2019/08/20 全球购物
求∏的近似值,直到最后一项的绝对值小于指定的数
2016/02/12 面试题
2015年幼儿园中班工作总结
2015/04/25 职场文书
小学体育组工作总结2015
2015/07/21 职场文书
股东协议书范本2016
2016/03/21 职场文书