Python标准库:Urllib库

Urllib库是Python用于操作Url的标准模块,Python2.x时分为Urllib和Urllib2,Python3.x时合并到Urllib里面。这里把常见的变化列举一下,便于查找修改。
官方文档:https://docs.python.org/3.6/library/urllib.html

Python2.xPython3.x
import urllib2import urllib.request,urllib.error
import urllibimport urllib.request,urllib.error,urllib.parse
import urlparseimport urllib.parse
urllib2.urlopenurllib.request.urlopen
urllib2.requesturllib.request.Request
urllib.quoteurllib.request.quote
urllib.urlencodeurllib.parse.urlencode
cookielib.CookieJarhttp.CookieJar
  1. 简单读取网页信息: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)含义
200OK一切正常
301Moved Permanently重定向到新的URL,永久性
302Found重定向到新的URL,非永久性
304Not Modified请求的资源未更新
400Bad Request非法请求
401Unauthorized请求未经授权
403Forbidden禁止访问
404Not Found没有找到对应页面
500Internal Server Error服务器内部错误
501Not 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)

作者:橄榄的世界
链接:https://www.jianshu.com/p/d68d3cbce5a0
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

说点什么

avatar
  Subscribe  
提醒