python requests 一种通过编码的反爬虫机制

  简介:遇到一个反爬虫机制,该网页为gbk编码网页,但是请求参数中,部分请求使用gbk编码,部分请求使用utf8编码,还设置了一些不进行编码的安全字符,在爬取的过程中形成了阻碍。

  提示:在认为参数设置正常,又无法正确爬取数据的情况下,通过response.requests.headers和esponse.requests.body与浏览器的请求数据的对比,会比较容易发现问题。

1.python的url编码函数

也有通用函数- decode(解码为unicode),encode(编码)

import requests  
from urllib.parse import urlencode  # 对整个字典进行编码
from requests.utils import quote,unquote  # 对字符串进行编码和解码
# 对整个字典进行编码,对于需要进行局部编码不太方便。
Signature:
urlencode(
    query,
    doseq=False,
    safe='',  # 不进行编码的字符串
    encoding=None,
    errors=None,
    quote_via=<function quote_plus at 0x0000027AB54DD678>,
)
Docstring:
Encode a dict or sequence of two-element tuples into a URL query string.

If any values in the query arg are sequences and doseq is true, each
sequence element is converted to a separate parameter.

If the query arg is a sequence of two-element tuples, the order of the
parameters in the output will match the order of parameters in the
input.

The components of a query arg may each be either a string or a bytes type.

The safe, encoding, and errors parameters are passed down to the function
specified by quote_via (encoding and errors only if a component is a str).
# 对字符串进行编码
Signature: requests.utils.quote(string, safe='/', encoding=None, errors=None) Docstring: quote('abc def') -> 'abc%20def'
# 对字符串进行解码
Signature: requests.utils.unquote(string, encoding='utf-8', errors='replace') Docstring: Replace %xx escapes by their single-character equivalent. The optional encoding and errors parameters specify how to decode percent-encoded sequences into Unicode characters, as accepted by the bytes.decode() method. By default, percent-encoded sequences are decoded with UTF-8, and invalid sequences are replaced by a placeholder character. unquote('abc%20def') -> 'abc def'.

2、模拟过程 - 以错误编码模式

这里还设置了一个安全符号,如果设置。"+"会进行编码。

# 如果错误的采用了网页编码进行访问
# 1. 请求数据
req1 = '+导出+++'
print('1.原始请求数据:',req1)
# 2. 自行编码以后发送出去的数据
req2 = quote(req1,encoding='gbk',safe='+')
print('2.浏览器编码后发出的数据:',req2)
# 3. 服务区接受的数据为req2,服务器会编码以后提交给后台
req3 = unquote(req2,encoding='gbk')
print('3.经服务器编码以后,后台接收到的数据:',req3)
# 4. 后台逆编码获取浏览器发送的原始数据
req4 = quote(req3,encoding='gbk',safe='+')
print('4.后台逆编码,重新得到浏览器发送的原始数据:',req4)
# 5. 后台再进行正确编码获取正确数据
req5 = unquote(req4,encoding='utf8')
print('5.后台逆编码,重新得到浏览器发送的原始数据,最终获取数据为乱码:',req5)

最后后台获取的数据是乱码,可以进行校准,如果是非正常编码数据则不进行处理。

1.原始请求数据: +导出+++
2.浏览器编码后发出的数据: +%B5%BC%B3%F6+++
3.经服务器编码以后,后台接收到的数据: +导出+++
4.后台逆编码,重新得到浏览器发送的原始数据: +%B5%BC%B3%F6+++
5.后台逆编码,重新得到浏览器发送的原始数据: +����+++

3、模拟过程-正确例子

# 1. 请求数据
req1 = '+导出+++'
print('1.原始请求数据:',req1)
# 2. 自行编码以后发送出去的数据
req2 = quote(req1,encoding='utf8',safe='+')
print('2.浏览器编码后发出的数据:',req2)
# 3. 服务区接受的数据为req2,服务器会编码以后提交给后台
req3 = unquote(req2,encoding='gbk')
print('3.经服务器编码以后,后台接收到的数据:',req3)
# 4. 后台逆编码获取浏览器发送的原始数据
req4 = quote(req3,encoding='gbk',safe='+')
print('4.后台逆编码,重新得到浏览器发送的原始数据:',req4)
# 5. 后台再进行正确编码获取正确数据
req5 = unquote(req4,encoding='utf8')
print('5.后台逆编码,重新得到浏览器发送的原始数据:',req5)
1.原始请求数据: +导出+++
2.浏览器编码后发出的数据: +%E5%AF%BC%E5%87%BA+++
3.经服务器编码以后,后台接收到的数据: +瀵煎嚭+++
4.后台逆编码,重新得到浏览器发送的原始数据: +%E5%AF%BC%E5%87%BA+++
5.后台逆编码,重新得到浏览器发送的原始数据: +导出+++
posted @ 2021-03-17 11:00  forxtz  阅读(482)  评论(0编辑  收藏  举报