Urllib库是Python用于操作Url的标准模块,Python2.x时分为Urllib和Urllib2,Python3.x时合并到Urllib里面。这里把常见的变化列举一下,便于查找修改。
官方文档:https://docs.python.org/3.6/library/urllib.html
Python2.x | Python3.x |
---|---|
import urllib2 | import urllib.request,urllib.error |
import urllib | import urllib.request,urllib.error,urllib.parse |
import urlparse | import urllib.parse |
urllib2.urlopen | urllib.request.urlopen |
urllib2.request | urllib.request.Request |
urllib.quote | urllib.request.quote |
urllib.urlencode | urllib.parse.urlencode |
cookielib.CookieJar | http.CookieJar |
- 简单读取网页信息:urllib需制定内容的解码方式,requests可自动解码。
import urllib.request
f = urllib.request.urlopen('http://python.org/')
html1 = f.read() #urlopen返回的是bytes对象,此时调用read()方法得到的也是bytes对象。
html2 = f.read().decode('utf-8') #要获取字符串内容,需要指定解码方式。因此,更常用html2的方式。
#还可以写成以下方式:
import urllib.request
with urllib.request.urlopen('http://python.org') as f:
html = f.read().decode('utf-8')
print(f.status)
print(html)
#html等价于requests库的r.text:
import requests
r = requests.get('http://python.org')
print(r.status_code)
print(r.text) #调用r.text时,Requests对象会使用其推测的文本编码自动解码。
print(r.encoding) #查询Requests对象使用的编码方式。
r.encoding = 'utf-8' #可直接通过赋值语句来改变Requests对象使用的编码方式。
2.urllib对含中文的URL进行手动编码
import urllib.request
a = urllib.request.quote("中文")
b = urllib.request.unquote(a)
print(a,b)
结果为:%E4%B8%AD%E6%96%87 中文
3.使用Request对象添加headers进行请求
import urllib.request
hds = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'}
req = urllib.request.Request('http://python.org')
req.add_header('User-Agent','Mozilla/5.0') ##注意参数是用“,”进行分隔。
#req.add_header('User-Agent',hds['User-Agent']) #另一种写法
with urllib.request.urlopen(req) as f: ##urlopen可放入url或Request对象
html = f.read().decode('utf-8')
#requests方法
import requests
hds = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'}
r = requests.get('http://python.org',headers=hds)
4.超时设置
import urllib.request
#加上timeout参数即可
f = urllib.request.urlopen(req,timeout=1)
f = urllib.request.urlopen('http://python.org',timeout=1)
#完整用法(正常响应1秒,若网站服务器性能不好时可适当调高timeout值)
import urllib.request
for i in range(10): #若超时,重复请求10次
try:
f = urllib.request.urlopen('http://python.org',timeout=1)
print(f.read().decode('utf-8')[:100])
break
except Exception as e:
print("出现异常: "+str(e))
# print(type(e))
#requests库类似
for i in range(10): #若超时,重复请求10次
try:
r = requests.get('http://python.org',timeout=0.25) #响应比urllib.request快
print(r.text[:100])
break
except Exception as e:
print("第{}次请求出现异常:".format(str(i+1))+str(e))
print(type(e))
5.下载HTML文件到本地
同理:图片、MP3、视频等文件格式也是用‘wb’形式下载。
#方法一:
import urllib.request
html = urllib.request.urlopen("http://www.baidu.com").read()
with open("1.html","wb") as f: #使用b模式写入,此时传入的html不需解码
f.write(html)
#方法二:最方便
#urlretrieve(url, filename=None, reporthook=None, data=None)
#reporthook(可选)是回调函数,可以显示下载进度。
#data(可选)指post到服务器的数据。
import urllib.request
urllib.request.urlretrieve("http://www.baidu.com",filename="1.html")
#urllib.request.urlretrieve("http://www.baidu.com","1.html")
#方法三:
import requests
r = requests.get("http://www.baidu.com")
with open("1.html",'wb') as f:
f.write(r.content)
# 其他格式:
urllib.request.urlretrieve("XXX.jpg",filename="1.jpg") #XXX表示服务器地址
urllib.request.urlretrieve("XXX.mp3",filename="1.mp3")
urllib.request.urlretrieve("XXX.rmvb",filename="1.rmvb")
6.get请求实例
get请求的url地址格式:http://网址?字段名1=内容1&字段名2=内容2
http://www.baidu.com/s?wd="python"&rqlang=cn # wd代表关键字, rqlang代表区域
import urllib.request
base_url = "http://www.baidu.com/s?wd="
keyword = "Python爬虫"
url = base_url + urllib.request.quote(keyword)
html = urllib.request.urlopen(url).read()
with open("1.html","wb") as f:
f.write(html)
#requests库
import requests
base_url = "http://www.baidu.com/s?wd="
keyword = "Python爬虫"
url = base_url + keyword #requests模块自动解析含中文的url
r = requests.get(url)
#print(r.url) #可查看解析后的url
with open("2.html","wb") as f:
f.write(r.content)
7.使用代理:urllib.request.ProxyHandler
import urllib.request
# 创建代理字典
proxy1={'sock5': 'localhost:1080'}
proxy2={'http': '183.51.191.203:9797'}
# 使用ProxyHandler方法生成处理器对象
proxy_handler = urllib.request.ProxyHandler(proxy1)
# 创建代理IP的opener实例
opener = urllib.request.build_opener(proxy_handler)
# 创建全局默认的open对象,使用urlopen()时会自动使用已经安装的opener对象
urllib.request.install_opener(opener)
a = urllib.request.urlopen("http://www.baidu.com").read().decode("utf8")
print(len(a))
8.开启Debuglog:urllib.request.HTTPHandler,urllib.request.HTTPSHandler
import urllib.request
http_handler = urllib.request.HTTPHandler(debuglevel=1)
https_handler = urllib.request.HTTPSHandler(debuglevel=1)
opener = urllib.request.build_opener(http_handler,https_handler)
urllib.request.install_opener(opener)
urllib.request.urlopen("https://www.baidu.com")
9.异常处理:URLError,子类HTTPError
- 触发URLError的原因有以下四种可能:
①连接不上服务器
②远程URL不存在
③无网络
④触发HTTPError
#写法一:
import urllib.request
import urllib.error
try:
# urllib.request.urlopen("http://www.google.com") #对应URLError
urllib.request.urlopen("https://login.taobao.com/member") #对应HTTPError
except urllib.error.HTTPError as e:
print(e.code,e.reason)
except urllib.error.URLError as e:
print(e.reason)
#写法二:
import urllib.request
import urllib.error
try:
#urllib.request.urlopen("http://www.google.com")
urllib.request.urlopen("https://login.taobao.com/member")
except urllib.error.URLError as e:
if hasattr(e,"code"): #hasattr是自带函数,详见下方。
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
'''
hasattr(obj, name, /)
Return whether the object has an attribute with the given name.
This is done by calling getattr(obj, name) and catching AttributeError.
'''
- HTTP状态码以及含义
状态码 (e.code) | 英文(e.reason) | 含义 |
---|---|---|
200 | OK | 一切正常 |
301 | Moved Permanently | 重定向到新的URL,永久性 |
302 | Found | 重定向到新的URL,非永久性 |
304 | Not Modified | 请求的资源未更新 |
400 | Bad Request | 非法请求 |
401 | Unauthorized | 请求未经授权 |
403 | Forbidden | 禁止访问 |
404 | Not Found | 没有找到对应页面 |
500 | Internal Server Error | 服务器内部错误 |
501 | Not Implemented | 服务器不支持实现请求所需要的功能 |
10.post请求
import urllib.request
import urllib.parse
url = "https://www.douban.com/accounts/login"
params = {'source':'index_nav',
'form_email':'XXXX', #账号
'form_password':'XXXX' #密码
}
postdata = urllib.parse.urlencode(params).encode('utf-8') #对数据进行编码
req = urllib.request.Request(url,postdata)
html = urllib.request.urlopen(req).read()
with open('1.html','wb') as f:
f.write(html)
#requests库
import requests
url = "https://www.douban.com/accounts/login"
params = {'source':'index_nav',
'form_email':'XXXX', #账号
'form_password':'XXXX' #密码
}
r = requests.post(url,params)
with open('1.html','wb') as f:
f.write(r.content)
#注:
urlencode:对key-value的字典数据进行编码转换,返回类似“a=XXX&b=XXX”的结果。
quote:对单个字符串进行编码转换,返回编码后的一串字符,多用于中文字符的编码。
11.使用cookies
import urllib.request
import urllib.parse
import http.cookiejar
url = "https://www.douban.com/accounts/login"
params = {'source':'index_nav',
'form_email':'XXXX', #账号
'form_password':'XXXX' #密码
}
postdata = urllib.parse.urlencode(params).encode('utf-8') #对数据进行编码
req = request.Request(url, postdata, method="POST") # 构建Request对象
#创建CookieJar对象
cj = http.cookiejar.CookieJar()
pro = urllib.request.HTTPCookieProcessor(cj)
opener = urllib.request.build_opener(pro)
# 创建全局默认的open对象,使用urlopen()时会自动使用已经安装的opener对象
urllib.request.install_opener(opener)
html1 = urllib.request.urlopen(req).read()
with open('1.html', 'wb') as f:
f.write(html1)
#requests库
import requests
url = "https://www.douban.com/accounts/login"
headers = {
'Cookie':'xxxxxxx'
}
r = requests.get(url,headers=headers)
print(r.text)