https://docs.python.org/3/library/urllib.html
urllib是Python内置的HTTP请求库,它主要包含4个模块
urllib.request模块提供了最基本的构造HTTP请求方法,利用它可以模拟浏览器的一个请求发起过程,同事它还带有处理授权验证(authentication)、重定向(redirection)、浏览器Cookies以及其他内容
import urllib.request
response = urllib.request.urlopen("https://www.python.org")
print(response.read().decode("utf-8"))
运行结果:
可以获取到网页的源码,我们可以使用type看看获取的类型:
import urllib.request
response = urllib.request.urlopen("https://www.python.org")
# 这是一个HTTPResponse对象,主要包含了read(),readinto(),getheader(name),getheaders()
# fileno()等方法,以及msg,version,status,reason,debuglevel,cloase属性
print(type(response))
import urllib.request
import urllib.parse
import socket
response = urllib.request.urlopen("https://www.python.org")
print(response.read().decode("utf-8"))
# 这是一个HTTPResponse对象,主要包含了read(),readinto(),getheader(name),getheaders()
# fileno()等方法,以及msg,version,status,reason,debuglevel,cloase属性
print(type(response))
print(response.status)
print(response.getheaders())
print(response.getheader("Server"))
urlopen()函数的API
urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
*, cafile=None, capath=None, cadefault=False, context=None):
# data 参数
data = bytes(urllib.parse.urlencode({
"word":"hello"}), encoding="utf-8")
response = urllib.request.urlopen("https://httpbin.org/post", data)
print(response.read())
这里我们传递了一个参数键是’word’,值是’hello’,它需要被转化为bytes类型,这个方法的第一个参数需要一个str类型没需要使用对urllib.parse.urlencode()方法将字典转化为字符串,第二个参数是编码格式,指定为utf-8.
我们传递的参数出现在form字段中了,表明是以post方式请求
# timeout 参数 可以通过设置这个超时时长来控制一个网页如果长时间未响应,就跳过它的抓取,可以利用try-except实现
try:
reponse = urllib.request.urlopen("http://httpbin.org/get", timeout=0.1)
except urllib.error.URLError as e:
# 如果错误原因是socket.timeou
if isinstance(e.reason, socket.timeout):
print("TIME OUT")
print(response.read())
我们设置了超时时间是0.1秒,如果超出这个时间没有得到响应就会认为请求异常,跑出个URLError,我们可以通过设置超时时间来控制一个网页如果长时间未响应,就跳过它的抓取
利用urlopen()方法可以实现最基本请求的发起,,但是不足以构建一个完整的请求,如果请求中需要加入head信息,就可以利用Request类来构建。
import urllib.request
request = urllib.request.Request("https://python.org")
response = urllib.request.urlopen(request)
print(response.read().decode("utf-8"))
我们依然使用openurl()方法来发送一个请求,这次方法的参数是一个Request对象。
Request()函数的API
Request (url, data=None, headers={
}, origin_req_host=None, unverifiable=False,method=None):
1、url: 必传,为请求地址
2、data :可选参数 如果要传,必须传byte(字节流)类型,如果是字典,可以用urllib.parse模块里的urlencode()编码
3、headers :请求头,是一个字典,我们可以在构造请求时通过headers参数直接构造,也可以通过调用请求实例的add_header()方法添加
添加请求头最常用的用法就是修改User-Agent来伪装浏览器,默认的User-Agent为Python-urllib,我们可以通过修改它来伪装浏览器
4、origin_req_host: 指的是请求方的host名称或者IP地址
5、unverifiable :表示这个请求是否是无法验证的,默认是false,意思是说用户没有权限来选择接受这个请求的结果
6、method: 是一个字符串,用来指示请求使用的方法,比如GET、POST
url = "http://httpbin.org/post"
headers = {
'User-Agent': 'Mozilla/4.0(compatible; MSIE 5.5; Windows NT)',
'Host': 'httpbin.org'
}
dict = {
'name': 'Germey'
}
data = bytes(parse.urlencode(dict), encoding='utf-8')
request = urllib.request.Request(url=url, headers=headers, data=data, method='POST')
# request.add_header('User-Agent','Mozilla/4.0(compatible; MSIE 5.5; Windows NT)')
try:
response = urllib.request.urlopen(request, timeout=1)
except urllib.error.URLError as e:
if isinstance(e.reson, socket.timeout):
print("TIME OUT")
print(response.read().decode('utf-8'))
urllib.request模块里的BaseHandler类,他是所有其他Handler类的父类,他提供了最基本的方法,default_open(),protocal_request()等
from urllib.request import HTTPPasswordMgrWithDefaultRealm,HTTPBasicAuthHandler,build_opener
from urllib.error import URLError
username = 'username'
password = 'password'
url = 'http://localhost:5000/'
p = HTTPPasswordMgrWithDefaultRealm()
# 利用add_password添加用户名和密码,这样建立一个处理验证的Handler
p.add_password(None, uri=url, user=username, passwd=password)
auth_handler = HTTPBasicAuthHandler(p)
# 利用build_opener构建一个opener,这个opener在发送请求时相当于已经验证成功了
opener = build_opener(auth_handler)
try:
# 利用 opener.open打开链接,完成验证
result = opener.open(url)
html = result.read().encode('utf-8')
print(html)
except URLError as e:
print(e.reason)
首先实例化HTTPBasicAuthHandler对象,参数是一个HTTPPasswordMgrWithDefaultRealm对象,利用add_password()添加进去用户名和密码,这样就建立了一个处理验证的Handler。然后再利用handler使用build_opener构建一个opener,这个opener在发送请求时就相当于验证成功了,然后在利用Opener的open()方法打开链接。
from urllib.error import URLError
from urllib.request import ProxyHandler,build_opener
# 使用ProxyHandler,参数是一个字典,键名是协议类型,键值是代理链接,可以添加多个代理
proxy_handler = ProxyHandler({
'http': 'http://127.0.0.1:9743',
'https': 'https://127.0.0.1:9743'
})
opener = build_opener(proxy_handler)
try:
response = opener.open('https://www.baidu.com')
print(response.read().encode('utf-8'))
except URLError as e:
print(e.reason)
使用ProxyHandler,参数是一个字典,键名是协议类型,值是代理链接,可以添加多个代理。
import http.cookiejar,urllib.request
cookie = http.cookiejar.CookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open("https://www.baidu.com")
for item in cookie:
print(item.name + '=' + item.value)
首先我们声明一个CookieJar,然后利用urllib.request.HTTPCookieProcessor来构建一个handler,最后利用build_opener构建出opener,最后执行open()函数即可。
# 进行文件存储
filename = 'D:/cookies.txt'
cookie = http.cookiejar.MozillaCookieJar(filename)
# 调用load方法来读取本地的cookie文件,获取到cookie内容
cookie.load('D://cookies.txt',ignore_expires=True, ignore_discard=True)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open("https://www.baidu.com")
cookie.save(ignore_discard=True, ignore_expires=True)
这里使用MozillaCookieJar代替CookieJar,在生成和读取文件时用到。
运行结果
LWPCookieJar同样可以读取和保存Cookeies,但是保存的格式和MozillaCookieJar不一样,它会保存成libwww-perl(LWP)格式的cookies文件
cookie = http.cookiejar.LWPCookieJar(filename)
# 进行Cookies读取
filename = 'D:/cookies.txt'
cookie = http.cookiejar.LWPCookieJar(filename)
cookie.load('D://cookies.txt',ignore_expires=True, ignore_discard=True)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open("https://www.baidu.com")
cookie.save(ignore_discard=True, ignore_expires=True)