我们为什么会害怕?这是由于我们做事不能当机立断,一旦犹豫不决的时候,我们便会畏缩。但如果能够对某件事作明确的判断时,不论有无价值,我们都不会畏缩。
--李小龙
①requests 是使用Apache2 licensed 许可证的 HTTP 库,用 python编写,比 urllib2 模块更简洁。
② Request 支持 HTTP 连接保持和连接池,支持使用 cookie 保持会话,支持文件上传,支持自动响应内容的编码,支持国际化的 URL和 POST 数据自动编码。
③ 在 python 内置模块的基础上进行了高度的封装,从而使得 python 进行网络请求时,变得人性化(几句代码),使用 Requests可以轻而易举的完成浏览器可有的任何操作。
④ requests 会自动实现持久连接keep-alive。
1发送请求前面介绍过 HTTP 的请求方法,GET,POST,HEAD等等,使用 requests 进行网络请求也很简单,导入 requests 模块,然后使用响应的请求方法访问某 URL ,两行代码搞定。
import requestsres = requests.get('http://hunter.com')
这里的 res 就是请求返回的 response 对象,我们可以从该对象中获取响应包的信息,下面会介绍到。其他的请求方法如下:
res = requests.post('http://hunter.com', data={'key': 'value'})res = requests.put('http://hunter.com', data={'key': 'value'})res = requests.delete('http://hunter.com')res = requests.head('http://hunter.com')res = requests.options('http://hunter.com')
四不四很简单
2传递URL参数当我们手工地给URL 传递参数的时候,通常情况下是这样:
① GET 传参(参数在 URL)
http://hunter.com/sql-test/getfind-injection.php?username=123&commit=submit
② POST传参(参数在请求包中)
使用 requests 模块也可以传参,而且参数是使用字典的 {'key':'value'} 的形式,且 GET 方法使用 params 接收参数,POST 方法使用 data 接收参数。
GET 传参
将参数制成 payload 然后传递给 params。
import requestsurl = "http://hunter.com"payload = {"key1": "value1", "key2": "value2"}r = requests.get(url=url, params=payload)print(r.url)
C:\Users\Lin\Desktop>python3 tmp.pyhttp://hunter.com/?key2=value2&key1=value1
还可以将一个列表作为值传入,由于字典的无序性,所以参数有时候会乱。
import requestsurl = "http://hunter.com"payload = {"key1": "value1", "key2": ["value2", "value3"]}r = requests.get(url=url, params=payload)print(r.url)
C:\Users\Lin\Desktop>python3 tmp.pyhttp://hunter.com/?key2=value2&key2=value3&key1=value1
POST 传参
注意:GET传参使用 params ,POST 传参使用 data
这里用本地搭建的一个环境做测试,一个简单的表单提交,如果登录成功就显示 login successful
import requestsurl = "http://hunter.com/sql-test/brute.php"payload = {"username": "admin", "password": "admin", "commit": "submit"}r = requests.post(url=url, data=payload)temp = r.content.decode() # 返回响应页面的源码print(res)
C:\Users\Lin\Desktop>python3 tmp.py brute 姓名: 密码: login successful
3响应对象
使用 Burpsuite 截取的响应包。
requests 模块的 response 对象可以看到以下的内容,包括但不限于。
功能 | 方法 |
响应内容编码(HTTP头的编码) | res.encoding |
响应内容编码(内容的编码) | res.apparent_encoding |
请求状态码 | res.status_code |
Text 方法返回的类型 | type(res.text) |
Content 方法返回的类型 | type(res.content) |
HTTP 响应内容的头部 | res.headers |
HTTP 请求内容的头部 | res.request.headers |
HTTP 响应 cookie | res.cookies |
字典的所有键值对 | res.hesders.items() |
text方法返回网页内容 | res.coding="utf-8" res.text |
content方法返回网页内容 | res.content.decode() |
响应头
查看响应头使用 res.headers,以字典的形式返回。
import requestsurl = 'http://hunter.com'res = requests.get(url=url)print(res.headers)
C:\Users\Lin\Desktop>python3 tmp.py{'Connection': 'Keep-Alive', 'Server': 'Apache/2.2.25 (Win32) mod_ssl/2.2.25 OpenSSL/0.9.8y PHP/5.2.17', 'Content-Length': '1355', 'Content-Type': 'text/html;charset=UTF-8', 'Date': 'Thu, 16 Jul 2020 09:58:14 GMT', 'Keep-Alive': 'timeout=5, max=100'}
分开字典的键值对,更方便地查看每一个字段。
import requestsurl = 'http://hunter.com'res = requests.get(url=url)for key, value in res.headers.items(): print(key, ':', end="") print(value)
C:\Users\Lin\Desktop>python3 tmp.pyDate :Thu, 16 Jul 2020 14:00:20 GMTServer :Apache/2.2.25 (Win32) mod_ssl/2.2.25 OpenSSL/0.9.8y PHP/5.2.17Content-Length :1355Keep-Alive :timeout=5, max=100Connection :Keep-AliveContent-Type :text/html;charset=UTF-8
单看某一个字段的内容
print("服务器使用的服务技术是:", res.headers['server'])
服务器使用的服务技术是:Apache/2.2.25 (Win32) mod_ssl/2.2.25 OpenSSL/0.9.8y PHP/5.2.17
响应内容
requests 模块中使用 response 对象的 text/content 方法获取响应的内容,使用 type 打印 text/content 的类型。
import requestsurl = 'http://hunter.com/sql-test/brute.php'res = requests.get(url=url)res.encoding = "utf-8"result1 = res.textresult2 = res.contentprint(type(result1))print(type(result2))
C:\Users\Lin\Desktop>python3 tmp.py
可以看到 res.text 的类型是 str 而 res.content 的类型是 bytes。
r.text | HTTP 响应内容的字符串形式,URL 对应的页面内容 |
r.content | HTTP 响应内容的二进制形式 |
两种类型相互转换有如下的关系:
result1 = res.text.encode()result2 = res.content.decode()
C:\Users\Lin\Desktop>python3 tmp.py
但是如果单纯地打印 res.text 会出现下面错误。
C:\Users\Lin\Desktop>python3 tmp.pyTraceback (most recent call last): File "tmp.py", line 8, in print(res.text)UnicodeEncodeError: 'gbk' codec can't encode character '\xe5' in position 211: illegal multibyte sequence
简单的说就是响应的内容中有些内容不能被 gbk 编码,解决的方法就是先将 response 响应内容的编码形式指定位 utf-8 然后再打印 res.text。
res.encoding = "utf-8"print(res.text)
显示正常的页面内容。
C:\Users\Lin\Desktop>python3 tmp.py brute 姓名: 密码:
打印 content 就 decode 一下(默认是以 utf-8 解码为字符串),将 bytes 转换为 str 即可。
print(res.content.decode())
C:\Users\Lin\Desktop>python3 tmp.py brute 姓名: 密码:
有时候 decode 之后还是出现某些字符不能被 gbk/utf-8 解析,这是后可以使用 ignore 忽略掉,绕过这些不能被解析的字符。
res.content.decode('utf-8','ignore')或者res.content.decode('gbk','ignore')
响应状态码
通过 response 对象的 status_code 返回响应的状态码。
import requestsurl = 'http://hunter.com/sql-test/brute.php'res = requests.get(url=url)print(res.status_code)
200 状态码是最常见的状态,表示服务器已成功处理请求,也说明请求的 URL 存在,在编写目录扫描器中常用此方法判断是否存在此目录。
resquests 模块还附带了一个内置地状态码查询对象,requests.codes.ok。
import requestsurl = "http://hunter.com/upload-labs/Pass-01/index.php"r = requests.get(url)temp = r.status_code == requests.codes.okprint(temp)
C:\Users\Lin\Desktop>python3 tmp.pyTrue
如果发送了一个错误请求(一个 4XX 客户端错误,或者 5XX 服务器错误响应),我们可以通过Response.raise_for_status() 来抛出异常:如果发送了一个正常请求,那么 response.raise_for _status 的值为 None。
import requestsurl = "http://hunter.com/404"r = requests.get(url)print(r.raise_for_status())
C:\Users\Lin\Desktop>python3 tmp.pyTraceback (most recent call last): File "tmp.py", line 5, in print(r.raise_for_status()) File "C:\Python35\lib\site-packages\requests\models.py", line 941, in raise_for_status raise HTTPError(http_error_msg, response=self)requests.exceptions.HTTPError: 404 Client Error: Not Found for url: http://hunter.com/404
4HTTP 代理
import requestsurl = "http://hunter.com"proxise = {"http": "http://127.0.0.1:8080", "https": "https://127.0.0.1:8080"}# verify=False 是设置不验证证书r = requests.get(url=url, proxies=proxise, verify=False)print(r.status_code)
requests 库其实是基于 urllib 编写的,对 urllib 进行了封装,使得使用时候的体验好了很多,现在 urllib 已经出到了3版本,功能和性能自然是提升了不少。所以,requests最新版本也是基于最新的 urllib3 进行封装。
在urllib2 时代对https的处理非常简单,只需要在请求的时候加上verify=False即可,这个参数的意思是忽略 https 安全证书的验证,也就是不验证证书的可靠性,直接请求,这其实是不安全的,因为证书可以伪造,不验证的话就不能保证数据的真实性。
在urllib3时代,官方强制验证https的安全证书,如果没有通过是不能通过请求的,虽然添加忽略验证的参数,但是依然会给出醒目的 Warning,这一点没毛病。
解决办法:添加两行代码 禁用 urllib3警告
import urllib3urllib3.disable_warnings()
5自定义请求头
有时候,目标经常会检查请求头的某些字段,看看是不是来自正常的客户端(浏览器等)的请求,以此来规避一些爬虫的骚扰,在这里我们就需要自定义请求头了,为了使自己的请求像是浏览器发出的,我们会将程序默认使用的 User-Agent 替换为浏览器的 User-Agent;像某些网站需要 cookie 才能访问的,我们要带上 cookie;如果还要检测 referer 字段的(防止 CSRF/XSS 跨站攻击),我们还要带上合法的 referer 字段。
我们可以通过 response.request.headers 来读取请求头。
import requestsurl = "http://hunter.com"r = requests.get(url)header = r.request.headersfor key, value in header.items(): print(key, ':', end='') print(value)
C:\Users\Lin\Desktop>python3 tmp.pyConnection :keep-aliveAccept :*/*Accept-Encoding :gzip, deflateUser-Agent :python-requests/2.23.0
自定义请求头也很简单,将内容包装成字典赋值给 headers 即可。
import requestsurl = "http://hunter.com"header = { 'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0', 'cookie': 'this is cookie', 'referer': 'this is referer'}r = requests.get(url=url, headers=header)header = r.request.headersfor key, value in header.items(): print(key, ':', end='') print(value)
C:\Users\Lin\Desktop>python3 tmp.pyAccept :*/*User-Agent :User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0Accept-Encoding :gzip, deflateConnection :keep-alivereferer :this is referercookie :this is cookie
6更多复杂的POST请求
POST传参除了上面介绍的可以传字典的形式之外,还可以传元组的形式,在表单中多个元素使用同一 key 的时候,这种方式尤其有效:
payload = (('key':'value1'),('key':'value2'))r = request.post(url=url,data=payload)
POST上传文件
注:图片的话推荐使用二进制的形式打开,否则可能会发生错误。
import requestsurl = "http://hunter.com/upload-labs/Pass-01/index.php"file = {"upload_file":open("picture.jpg","rb")} #上传图片r = requests.post(url=url,files=file)r.encoding = 'utf-8'res = r.textprint(res)
你可以显式地设置文件名,文件类型和请求头:
files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}r = requests.post(url, files=files)
7重定向和请求历史
默认情况下,除了 HEAD, Requests 会自动处理所有重定向。
可以使用响应对象的 history
方法来追踪重定向。
Response.history
是一个 Response
对象的列表,为了完成请求而创建了这些对象。这个对象列表按照从最老到最近的请求进行排序。
例如,Github 将所有的 HTTP 请求重定向到 HTTPS:
>>> r = requests.get('http://github.com')>>> r.url'https://github.com/'>>> r.status_code200>>> r.history[301]>]
如果你使用的是GET、OPTIONS、POST、PUT、PATCH 或者 DELETE,那么你可以通过 allow_redirects
参数禁用重定向处理:
>>> r = requests.get('http://github.com', allow_redirects=False)>>> r.status_code301>>> r.history[]
如果你使用了 HEAD,你也可以启用重定向:
>>> r = requests.head('http://github.com', allow_redirects=True)>>> r.url'https://github.com/'>>> r.history[301]>]
8超时
你可以告诉 requests 在经过以 timeout
参数设定的秒数时间之后停止等待响应。基本上所有的生产代码都应该使用这一参数。如果不使用,你的程序可能会永远失去响应:
>>> requests.get('http://github.com', timeout=0.001)Traceback (most recent call last): File "", line 1, in <module>requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)
9错误和异常注意 timeout 仅对连接过程有效,与响应体的下载无关。timeout 并不是整个下载响应的时间限制,而是如果服务器在 timeout 秒内没有应答,将会引发一个异常(更精确地说,是在 timeout 秒内没有从基础套接字上接收到任何字节的数据时)If no timeout is specified explicitly, requests do not time out.
遇到网络问题(如:DNS 查询失败、拒绝连接等)时,Requests 会抛出一个 ConnectionError
异常。
如果 HTTP 请求返回了不成功的状态码, Response.raise_for_status()
会抛出一个 HTTPError
异常。
若请求超时,则抛出一个 Timeout
异常。
若请求超过了设定的最大重定向次数,则会抛出一个 TooManyRedirects
异常。
所有 Requests 显示抛出的异常都继承 requests.exceptions.RequestException.
10简易目录扫描器1.目录扫描原理
①读取字典文件,拼接 URL
② HTTP GET请求URL
③判断状态码,输出存在目录
2.字典文件读取
①方法一:
使用f = open() 打开文件之后要用f.close() 关闭文件
open(filename,mode) 其中 mode可以是r , w , a
mode | 功能 |
r | 只读 |
w | 写操作,并且对之前的内容进行覆盖 |
a | 追加内容 |
②方法二:
使用withopen("filename.txt","r") as f: 打开文件,在文件读取结束之后会自动关闭文件。
f.readline() | 读取一行 |
f.readlines() | 读取多行,保存在列表中 |
f.read(10) | 读取10个字节 |
3.参数优化
使用sys 模块
C:\>python3homework2.py http://hunter.com/ dir.txt
sys.argv[0] 对应的时绝对路径下的文件路径如:homework2.py
sys.argv[1]对应第一个参数如:http://hunter.com
import requestsimport sys#参数优化,用户在控制台输入参数url = sys.argv[1]dic = sys.argv[2]with open("dir.txt","r") as f: for line in f.readlines(): line = line.strip() final_url = url + "/" + line res = requests.get(url=final_url)if res.status_code == 200:print("url:" + res.url + " exist")
C:\Users\Lin\Desktop\>python3 homework2.py http://hunter.com/ dir.txturl:http://hunter.com/sql-php/ existurl:http://hunter.com/xss-php/ exist
最后声明
以上内容主要参考自 requests 初级用法,链接如下:
https://requests.readthedocs.io/zh_CN/latest/user/quickstart.html
我是匠心,一个在清流旁默默磨剑的匠人,希望有一天能利刃出鞘,仗剑走江湖。
好文!点个在看!