鱼C论坛

 找回密码
 立即注册
查看: 158|回复: 3

[技术交流] Urllib和Requests库实现同样功能的Get和Post比较

[复制链接]
发表于 2024-5-29 05:59:37 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 591821661 于 2024-5-29 06:13 编辑

起因是在写爬虫的时候还在Urllib库和Requests库之间纠结。于是心血来潮抓包比较一下两个库的区别。
目前使用Urllib库的主要原因是因为它可以全局共享一个Cookie池,优点是属于原生自带的库,但是写法上要比Requests多很多繁琐的步骤。

Snipaste_2024-05-29_05-54-29.png
Connection: keep-alive:保持连接打开,可以提高性能和效率,适合频繁请求的场景。
Connection: close:在每个请求后关闭连接,简化连接管理,适合单次请求的场景。
Snipaste_2024-05-29_06-12-49.png
可以看到库的维护者把这个事情列成了TODO项(待做)
Snipaste_2024-05-29_06-10-38.png
Accept: */* 当客户端对返回的数据类型没有特定要求时,可以使用 Accept: */*。这通常用于浏览器和一些 HTTP 客户端库的默认设置,确保客户端不会因为不支持某种特定类型而无法处理响应。

Accept-Encoding: identity 即告诉服务器希望接收未经压缩的响应数据
大多数现代浏览器和 HTTP 客户端会自动处理各种内容编码方式,并默认支持压缩编码(如 gzip, deflate 等)。因此,显式使用 Accept-Encoding: identity 的场景比较少见,通常用于调试或在特定情况下需要获取未经压缩的响应数据时。
import urllib
import urllib.request
import http.cookiejar
import json
import socket
import requests

# Fiddle 抓包软件 Tool -> Fiddler Options -> Connections -> Listening port 7777
proxy = '127.0.0.1:7777'

def cake_init(cookies_filename="cookies.txt", UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 HBPC/11.0.6.301', proxy='127.0.0.1:7777'):
    socket.setdefaulttimeout(60) # 设置60秒超时
    proxy_support = urllib.request.ProxyHandler({'http':proxy,'https':proxy}) if proxy else urllib.request.ProxyHandler({})
    cookiejar = http.cookiejar.MozillaCookieJar(cookies_filename) # 加载cookies内容 cookiejar.save()能够保存文件
    cookie_support = urllib.request.HTTPCookieProcessor(cookiejar)
    opener = urllib.request.build_opener(proxy_support,cookie_support)# urllib钢铁侠组配
    opener.addheaders = [
                         ('User-agent', UA),
                         ('Accept', '*/*'),
                         # ('referer', "https://www.douyin.com/"),
                         # ('authority', 'www.douyin.com'),
                         ('Accept-Encoding','gzip, deflate'), # 默认是identity即告诉服务器希望接收未经压缩的响应数据
                         ]
    urllib.request.install_opener(opener) #urllib钢铁侠开机初始化
    return cookiejar

def getjson(url):
    response  = urllib.request.urlopen(url)
    data_json = json.loads(response.read())
    return data_json

def getjson_post(url,data):
    req       = urllib.request.Request(url)
    
    # Post的数据类型选择
    # data_coded = urllib.parse.urlencode(data).encode('utf-8') 
    # req.add_header('Content-Type', 'application/x-www-form-urlencoded')
    
    # 提交Json要改变默认的Content-Type类型
    data_coded = json.dumps(data).encode('utf-8')
    req.add_header('Content-Type', 'application/json; charset=utf-8')
    # 如果需要对单个请求进行进一步客制化 其中的urlopen()还需要生成request实例进行自定义。
    response  = urllib.request.urlopen(req,data_coded)
    data_json = json.loads(response.read())
    return data_json

def getjson_header(url,header_dict):
    # header_list = [('User-agent', UA),]
    req  = urllib.request.Request(url)
    for key in header_dict:
        req.add_header(key, header_dict[key])
    response  = urllib.request.urlopen(req)
    data_json = json.loads(response.read())
    return data_json

# 初始化容器,使其能够保存Cookies,
cookiejar = cake_init(proxy=proxy)
# cookiejar.save()

ip_api_url = 'http://ip-api.com/json/?fields=61439'

data = {'a':1,'b':2}
# 对跨站检测有用,防止视频链接被其他网站直接调用,会检测视频来源
header_dict = {'Referer':'https://www.douyin.com/'}

s_get_dict = getjson(ip_api_url)
s_get_dict = getjson_post(ip_api_url,data)
s_get_dict = getjson_header(ip_api_url,header_dict)

response = requests.get(ip_api_url,proxies={'https':proxy})
response = requests.post(ip_api_url,json=data,proxies={'https':proxy})
res_json = response.json()

print('----------------------IP Information Begin--------------------------')
for key in s_get_dict:
    print('%s : %s' % (key, s_get_dict[key]))
print('----------------------IP Information End--------------------------\n')


print('----------------------IP Information Begin--------------------------')
for key in res_json:
    print('%s : %s' % (key, res_json[key]))
print('----------------------IP Information End--------------------------\n')
分别使用Fiddler的抓包方法

1.png 2.png 4.png 5.png

总结: Requests库更加简洁,封装的也更加全面。
3.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-5-29 06:00:02 | 显示全部楼层
在Python中,我们可以使用urllib库和requests库来发送HTTP请求,实现GET和POST功能。这两个库都可以实现相同的功能,但在使用上有一些差异。

首先,我们来看一下使用urllib库实现GET请求的代码:
import urllib.request

# 发送GET请求
response = urllib.request.urlopen(url)
html = response.read()
print(html)

使用urllib库时,我们需要先导入`urllib.request`模块,然后使用`urlopen()`函数发送GET请求,接着使用`read()`方法读取响应内容。

接下来,让我们来看一下使用urllib库实现POST请求的代码:
import urllib.request
import urllib.parse

# 构造请求数据
data = {'key1': 'value1', 'key2': 'value2'}
data = urllib.parse.urlencode(data).encode('utf-8')

# 发送POST请求
req = urllib.request.Request(url, data=data, method='POST')
response = urllib.request.urlopen(req)
html = response.read()
print(html)

使用urllib库发送POST请求时,我们需要使用`urllib.parse.urlencode()`函数将请求参数编码为URL格式,并使用`encode()`方法将其转换为字节流。然后,我们使用`urllib.request.Request()`构造一个请求对象,通过设置`method`参数为'POST',并传入请求数据,再通过`urlopen()`函数发送请求。

接下来,让我们看一下使用requests库实现相同功能的代码:
import requests

# 发送GET请求
response = requests.get(url)
html = response.text
print(html)

使用requests库时,我们只需要导入`requests`模块,使用`get()`函数发送GET请求,然后使用`text`属性获取响应内容。

再来看看使用requests库实现POST请求的代码:
import requests

# 构造请求数据
data = {'key1': 'value1', 'key2': 'value2'}

# 发送POST请求
response = requests.post(url, data=data)
html = response.text
print(html)

使用requests库发送POST请求时,我们只需要使用`post()`函数,并传入请求参数即可。

从上面的例子可以看出,使用requests库相比urllib库更加简洁和方便。requests库封装了更多的功能,如自动处理cookie,更友好的错误提示等。因此,如果可以选择,我建议使用requests库来发送HTTP请求。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-5-29 06:16:05 | 显示全部楼层
如果要运行代码的话,第十行把Proxy设置为空字符串
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-5-29 06:16:37 | 显示全部楼层
591821661 发表于 2024-05-29 06:16
如果要运行代码的话,第十行把Proxy设置为空字符串


如果你想要运行代码,请确保你已经安装了所需的库,并将第十行的proxy参数设置为空字符串。这样代码中的发送请求部分将会使用默认的网络设置,而不是通过代理服务器发送请求。

代码示例:
import urllib.request
import urllib.parse
import http.cookiejar
import json
import socket
import requests

# Fiddle 抓包软件 Tool -> Fiddler Options -> Connections -> Listening port 8888
proxy = ''

def cake_init(cookies_filename="cookies.txt", UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 HBPC/11.0.6.301', proxy=''):
    socket.setdefaulttimeout(60) # 设置60秒超时
    proxy_support = urllib.request.ProxyHandler({'http':proxy,'https':proxy}) if proxy else urllib.request.ProxyHandler({})
    cookiejar = http.cookiejar.MozillaCookieJar(cookies_filename) # 加载cookies内容 cookiejar.save()能够保存文件
    cookie_support = urllib.request.HTTPCookieProcessor(cookiejar)
    opener = urllib.request.build_opener(proxy_support,cookie_support)# urllib钢铁侠组配
    opener.addheaders = 
    urllib.request.install_opener(opener) #urllib钢铁侠开机初始化
    return cookiejar

def getjson(url):
    response  = urllib.request.urlopen(url)
    data_json = json.loads(response.read())
    return data_json

def getjson_post(url,data):
    req       = urllib.request.Request(url)
    
    # Post的数据类型选择
    # data_coded = urllib.parse.urlencode(data).encode('utf-8') 
    # req.add_header('Content-Type', 'application/x-www-form-urlencoded')
    
    # 提交Json要改变默认的Content-Type类型
    data_coded = json.dumps(data).encode('utf-8')
    req.add_header('Content-Type', 'application/json; charset=utf-8')
    # 如果需要对单个请求进行进一步客制化 其中的urlopen()还需要生成request实例进行自定义。
    response  = urllib.request.urlopen(req,data_coded)
    data_json = json.loads(response.read())
    return data_json

def getjson_header(url,header_dict):
    # header_list = 
    req  = urllib.request.Request(url)
    for key in header_dict:
        req.add_header(key, header_dict)
    response  = urllib.request.urlopen(req)
    data_json = json.loads(response.read())
    return data_json

# 初始化容器,使其能够保存Cookies,
cookiejar = cake_init(proxy=proxy)
# cookiejar.save()

ip_api_url = 'http://ip-api.com/json/?fields=61439'

data = {'a':1,'b':2}
# 对跨站检测有用,防止视频链接被其他网站直接调用,会检测视频来源
header_dict = {'Referer':'https://www.douyin.com/'}

s_get_dict = getjson(ip_api_url)
s_get_dict = getjson_post(ip_api_url,data)
s_get_dict = getjson_header(ip_api_url,header_dict)

response = requests.get(ip_api_url,proxies={'https':proxy})
response = requests.post(ip_api_url,json=data,proxies={'https':proxy})
res_json = response.json()

print('----------------------IP Information Begin--------------------------')
for key in s_get_dict:
    print('%s : %s' % (key, s_get_dict))
print('----------------------IP Information End--------------------------\n')


print('----------------------IP Information Begin--------------------------')
for key in res_json:
    print('%s : %s' % (key, res_json))
print('----------------------IP Information End--------------------------\n')

希望这可以帮助到你!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-22 18:30

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表