urllib 和urllib2都是接受URL请求的相关模块,但是urllib2可以接受一个Request类的实例来设置URL请求的headers;urllib仅可以接受URL,这意味着,你不可以伪装你的User Agent字符串等。
urllib提供urlencode方法用来GET查询字符串的产生,而urllib2没有。这是为何urllib常和urllib2一起使用的原因。
urllib.urlretrieve函数以及urllib.quote等一系列quote和unquote功能没有被加入urllib2中,因此有时也需要urllib的辅助。
quote(),unquote(),quote_plus(),unquote_plus(),urlencode() ,pathname2url(),url2pathname()
urllib中还提供了一些辅助方法,用于对url进行编码、解码。url中是不能出现一些特殊的符号的,有些符号有特殊的用途。我们知道以get方式提交数据的时候,会在url中添加key=value这样的字符串,所以在value中是不允许有'=',因此要对其进行编码;与此同时服务器接收到这些参数的时候,要进行解码,还原成原始的数据。这个时候,这些辅助方法会很有用:
urllib.quote(string[, safe]):对字符串进行编码。参数safe指定了不需要编码的字符;
urllib.unquote(string) :对字符串进行解码;
urllib.quote_plus(string [ , safe ] ) :与urllib.quote类似,但这个方法用'+'来替换' ',而quote用'%20'来代替' '
urllib.unquote_plus(string ) :对字符串进行解码;
urllib.urlencode(query[, doseq]):将dict或者包含两个元素的元组列表转换成url参数。例如 字典{'name': 'dark-bull', 'age': 200}将被转换"name=dark-bull&age=200"
urllib.pathname2url(path):将本地路径转换成url路径;
urllib.url2pathname(path):将url路径转换成本地路径;
python3对urllib和urllib2进行了重构,拆分成了urllib.request,urllib.response, urllib.parse, urllib.error等几个子模块,这样的架构从逻辑和结构上说更加合理。urllib库无需安装,python3自带。python 3.x中将urllib库和urilib2库合并成了urllib库。
更多python 2 python 3版本的urllib区别,参考:python2&3.html#urllib
urllib2.urlopen() 变成了 urllib.request.urlopen()
urllib2.Request() 变成了 urllib.request.Request()
python2中的 cookielib 改为 http.cookiejar
import http.cookiejar 代替 import cookielib
urljoin 现在对应的函数是 urllib.parse.urljoin
import urllib.parse,urllib.request
data = 'name = ~a+3'
data1 = urllib.parse.quote(data)
print(data1) # result: name%20%3D%20%7Ea%2B3
print(urllib.parse.unquote(data1)) # result: name = ~a+3
data2 = urllib.parse.quote_plus(data)
print(data2) # result: name+%3D+%7Ea%2B3
print(urllib.parse.unquote_plus(data2)) # result: name = ~a+3
data3 = urllib.parse.urlencode({'name': 'dark-bull', 'age': 200})
print(data3) # result: age=200&name=dark-bull
data4 = urllib.request.pathname2url(r'd:/a/b/c/23.php')
print(data4) # result: ///D|/a/b/c/23.php
print(urllib.request.url2pathname(data4)) # result: D:/a/b/c/23.php
import urllib
response = urllib.urlopen('http://127.0.0.1/')
the_page = response.read()
POST:
import urllib
import urllib2
url = 'http://www.someserver.com/cgi-bin/register.cgi'
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'# 将user_agent写入头信息
values = {'name' : 'who','password':'123456'}
headers = { 'User-Agent' : user_agent }
data = urllib.urlencode(values)
request = urllib2.Request(url, data, headers)
response = urllib2.urlopen(request)
the_page = response.read()
GET:
import urllib
import urllib2
url = 'http://www.baidu.com/s'
values = {'wd':'D_in'}
data = urllib.urlencode(values)
geturl = url + "?" + data
request = urllib2.Request(geturl)
response = urllib2.urlopen(request)
print response.read()
response.close()
#post data可以直接送字符串,特别是有特殊符号时
post data = '{"stockIds":[30],"startDate":"2015-05-15T09:05:34.501Z","endDate":"2020-05-15T09:05:34.501Z","granularities":["q"],"expressionCaculateTypes":["t"]}'
# python2
import urllib
urllib.urlretrieve(url, filename)
# python3
import urllib.request
urllib.request.urlretrieve(url, filename)
默认的是FileCookieJar没有实现save函数。
而MozillaCookieJar或LWPCookieJar都已经实现了。
所以可以用MozillaCookieJar或LWPCookieJar,去自动实现cookie的save。
建议用LWPCookieJar,其保存的cookie,易于人类阅读
FileCookieJar(filename)
创建FileCookieJar实例,检索cookie信息并将信息存储到文件中,filename是文件名。
MozillaCookieJar(filename)
创建与Mozilla cookies.txt文件兼容的FileCookieJar实例。
LWPCookieJar(filename)
创建与libwww-perl Set-Cookie3文件兼容的FileCookieJar实例。
另外,补充一下urllib2的方法:
1、geturl():
这个返回获取的真实的URL,这个很有用,因为urlopen(或者opener对象使用的)或许会有重定向。获取的URL或许跟请求URL不同。
URL重定向(URL redirection,或称网址重定向或网域名称转址),是指当使用者浏览某个网址时,将他导向到另一个网址的技术。常用在把一串很长的网站网址,转成较短的网址。因为当要传播某网站的网址时,常常因为网址太长,不好记忆;又有可能因为换了网路的免费网页空间,网址又必须要变更,不知情的使用者还以为网站关闭了。这时就可以用网路上的转址服务了。这个技术使一个网页是可借由不同的统一资源定位符(URL)连结。
>>> import urllib2
>>> url = "http://www.baidu.com"
>>> req = urllib2.Request(url)
>>> response = urllib2.urlopen(req)
>>> response.geturl()
'http://www.baidu.com'
>>> print response.info()
Date: Fri, 28 Mar 2014 03:30:01 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: Close
Vary: Accept-Encoding
Set-Cookie: BAIDUID=AF7C001FCA87716A52B353C500FC45DB:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: BDSVRTM=0; path=/
Set-Cookie: H_PS_PSSID=1466_5225_5288_5723_4261_4759_5659; path=/; domain=.baidu.com
P3P: CP=" OTI DSP COR IVA OUR IND COM "
Expires: Fri, 28 Mar 2014 03:29:06 GMT
Cache-Control: private
Server: BWS/1.1
BDPAGETYPE: 1
BDQID: 0xea1372bf0001780d
BDUSERID: 0
2、默认情况下会针对 HTTP 3XX 返回码自动进行 redirect 动作(URL重定向),无需人工配置。要检测是否发生了 redirect 动作,只要检查一下 Response 的 URL 和 Request 的 URL 是否一致就可以了。
import urllib2
my_url = 'http://www.google.cn'
response = urllib2.urlopen(my_url)
redirected = response.geturl() == my_url
print redirected
my_url = 'http://rrurl.cn/b1UZuP'
response = urllib2.urlopen(my_url)
redirected = response.geturl() == my_url
print redirected
3、Debug Log
使用 urllib2 时,可以通过下面的方法把 debug Log 打开,这样收发包的内容就会在屏幕上打印出来,方便调试,有时可以省去抓包的工作
import urllib2
httpHandler = urllib2.HTTPHandler(debuglevel=1)
httpsHandler = urllib2.HTTPSHandler(debuglevel=1)
opener = urllib2.build_opener(httpHandler, httpsHandler)
urllib2.install_opener(opener)
response = urllib2.urlopen('http://www.google.com')
GET:
import requests
def get_page():
url = 'http://cip.cc/'
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36',
}
params = {
'query': word
}
response = requests.get(url, headers=headers, params=params)
return response
response = get_page()
print(response.text)
print(response.status_code)
POST:
import requests
import json
def get_page():
url = 'https://www.xxx.com/api'
headers = {
'Content-Type': "application/json",
# 'Content-Type': "application/x-www-form-urlencoded",
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36',
}
data = {
'page': '1',
'keywords': '2'
}
response = requests.post(url=url, headers=headers, data=json.dumps(data))
# response = requests.post(url=url, headers=headers, data=data)
return response
print(response.text)
print(response.status_code)
response_json = json.loads(response.text)
response_data = (response_json['data'])
在进行接口测试的时候,我们会调用多个接口发出多个请求,在这些请求中有时候需要保持一些共用的数据,例如cookies信息。
1、requests库的session对象能够帮我们跨请求保持某些参数,也会在同一个session实例发出的所有请求之间保持cookies。
s = requests.session()
req_param = '{"belongId": "300001312","userName": "alitestss003","password":"pxkj88","captcha":"pxpx","captchaKey":"59675w1v8kdbpxv"}'
res = s.post('http://test.e.fanxiaojian.cn/metis-in-web/auth/login', json=json.loads(req_param))
# res1 = s.get("http://test.e.fanxiaojian.cn/eos--web/analysis/briefing")
print(res.cookies.values()) 获取登陆的所有session
2、requests库的session对象还能为我们提供请求方法的缺省数据,通过设置session对象的属性来实现
eg:
# 创建一个session对象
s = requests.Session()
# 设置session对象的auth属性,用来作为请求的默认参数
s.auth = ('user', 'pass')
# 设置session的headers属性,通过update方法,将其余请求方法中的headers属性合并起来作为最终的请求方法的headers
s.headers.update({'x-test': 'true'})
# 发送请求,这里没有设置auth会默认使用session对象的auth属性,这里的headers属性会与session对象的headers属性合并
r = s.get('http://httpbin.org/headers', headers={'x-test2': 'true'})
上面的请求数据等于:{'Authorization': 'Basic dXNlcjpwYXNz', 'x-test': 'false'}
# 查看发送请求的请求头
r.request.headers #打印响应中请求的所有header数据
res3 = s.get("http://pre.n.cn/irs-web/sso/login",cookies = cookie)
print(res3.request.headers.get("Cookie").split("IRSSID=")[-1])
print(type(res3.request.headers.get("Cookie").split("IRSSID=")[-1]))
print(res3.request._cookies)
# 问题:(python2: urllib2)
URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661)>
# 问题:(python3: urllib.request)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)>
# 解决方法:
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
# 问题:(requests)
SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661)
# 解决方法:
request = requests.get(url)
request = requests.get(url, verify=False)
# 问题:(urllib2)
URLError: <urlopen error [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:661)>
# 解决方法:
import ssl
ssl._DEFAULT_CIPHERS = 'ALL'
# 问题:(requests)
SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:661)
# 解决方法:
import requests.packages.urllib3.util.ssl_
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'ALL'
# urllib2
"C:\Python27\Lib\ssl.py"
# requests
"C:\Python27\Lib\site-packages\urllib3\util\ssl_.py"
Warning (from warnings module):
File "C:\Python27\lib\site-packages\urllib3\connectionpool.py", line 852
InsecureRequestWarning)
InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
# 解决方法:
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
headers = {"Accept-Encoding": "gzip, deflate"}
# python2
import urllib2, httplib
request = urllib2.Request(jsonpUrl,None,values)
response = urllib2.urlopen(request)
jsonpPage = response.read()
response.close()
#解压缩
import StringIO, gzip
compressedstream = StringIO.StringIO(jsonpPage)
gziper = gzip.GzipFile(fileobj=compressedstream)
jsonpPage = gziper.read()
return jsonpPage
# python3
import urllib.request as request
r = request.Request(url,None,self.headers )
response = request.urlopen(r)
page = response.read()
#print(page[0:3]) # b'\x1f\x8b\x08' 即为gzip压缩
#解压缩
# 方式1:
import gzip
page = gzip.decompress(page)
# 方式2:
import gzip
from io import BytesIO
buff = BytesIO(page)
f = gzip.GzipFile(fileobj=buff)
page = f.read()
1.http请求中Form Data和Request Playload的区别:
Ajax post请求中常用的两种参数形式:form data 和 request payload
get请求的时候,我们的参数直接反映在url里面,为key1=value1&key2=value2形式,如果是post请求,那么表单参数是在请求体中,也是以key1=value1&key2=value2的形式在请求体中。通过chrome的开发者工具可以看到如下
a.Form Data类型:
这种情况有两种处理方式,一个是把这个post请求变成get请求,即把请求参数通过"?key1=value1&key2=value2"拼接在url当中,然后以get方式请求就可以了:response = requests.get(url,headers=headers),其中url为拼接的url
另一种是仍然用post请求,将参数放在data中:response = requests.post(url,headers=headers,data=data),其中url为post url.
注意上图中红圈内的内容,这里请求头中的Content-Type为application/x-www-form-urlencoded,点击Form Data旁边的view source,变成了key1=value1&key2=value2形式,如下图,这时你可以将这部分内容加到post的Request URL后面使它变成一个get请求,就可以获取到数据了。
b.Request Payload类型
同样在chrome浏览器开发者工具中可以看到它们不同的地方,Content-Type为application/json,表明需要传的是一个json类型的对象,点击view source,如下图
自动变成了json类型,这时必须发post请求,将这json对象传入才可获取数据。形如:
response = requests.post(url, headers=headers, data=json.dumps(data))
response = requests.post(url, headers=headers, json=data)
相比普通的post,这个post参数中的data一定要序列化才行。
import requests
def get_page():
url = 'http://cip.cc/'
headers = {
#"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36"
"User-Agent": "curl/7.55.1"
}
params = {
}
response = requests.get(url, headers=headers, params=params, proxies={"http": "106.54.128.253:999"})
return response
response = get_page()
print(response.text)
快代理:
https://www.kuaidaili.com/free/inha/
厂商名称 地址
66代理 http://www.66ip.cn/
西刺代理 https://www.xicidaili.com
全网代理 http://www.goubanjia.com
云代理 http://www.ip3366.net
IP海 http://www.iphai.com
快代理 https://www.kuaidaili.com
免费代理IP库 http://ip.jiangxianli.com
小幻代理 https://ip.ihuan.me/
注意:如果请求的ip是https类型的,但代理的ip是只支持http的,那么还是使用本机的ip,
如果请求的ip是http类型的,那么代理的ip一定要是http的,前面不能写成https,否则使用本机IP地址
通常情况下:
response = requests.get("http://www.xxx.com")
response_text = response.text
response.text 返回的是Unicode型的数据,文本数据用
response.content 返回的是bytes型的数据,图片等数据用
有部分网页是utf-8编码,但text却是乱码,解决办法:
response = requests.get("http://www.xxx.com")
response.encoding = 'utf-8'
response_text = response.text