python urlib库

官方参考文档: https://docs.python.org/fr/3.6/library/urllib.html

Python3.x中,我们可以使用urlib这个组件抓取网页,urllib是一个URL处理包,这个包中集合了一些处理URL的模块 。
1、urllib.request模块是用来打开和读取URLs的。
2、urllib.error模块包含一些有urllib.request产生的错误,可以使用try进行捕捉处理。
3、urllib.parse模块包含了一些解析URLs的方法。
4、urllib.robotparser模块用来解析robots.txt文本文件.它提供了一个单独的RobotFileParser类,通过该类提供的can_fetch()方法测试爬虫是否可以下载一个页面。

urllib.request.urlopen() 这个接口函数就可以很轻松的打开一个网站,读取并打印信息。

from urllib import request 


if __name__ == "__main__": 
	response = request.urlopen("http://fanyi.baidu.com") 
	html = response.read() 
	print(html) 

1、request.urlopen()打开和读取URLs信息,返回对象response 可以调用read(),进行读取。
2、print(),将读到的信息打印出来。
3、其实这就是浏览器接收到的信息,只不过我们在使用浏览器的时候,浏览器已经将这些信息转化成了界面信息供我们浏览。

网页编码
虽然我们已经成功获取了信息,但是显然他们都是二进制的乱码 ,可以通过简单的decode()命令将网页的信息进行解码 。

from urllib import request 


if __name__ == "__main__": 
	response = request.urlopen("http://fanyi.baidu.com/") 
	html = response.read() 
	html = html.decode("utf-8") 
	print(html) 
	

自动获取网页编码
chardet ,第三方库,用来判断编码的模块 ,使用chardet.detect()方法,判断网页的编码方式 。
安装:pip install chardet

from urllib import request 
import chardet 


if __name__ == "__main__": 
	response = request.urlopen("http://fanyi.baidu.com/") 
	html = response.read() 
	charset = chardet.detect(html) 
	print(charset) 

Request对象
反爬虫机制: 1、封杀爬虫程序 。2、封杀指定IP 。3、 封杀非人操作的程序 。

如果需要执行更复杂的操作,比如增加 HTTP 报头,必须创建一个 Request 实例来作为urlopen()的参数;而需要访问的 url 地址则作为 Request 实例的参数。

from urllib import request 


if __name__ == "__main__": 
	req = request.Request("http://fanyi.baidu.com/") 
	response = request.urlopen(req)
	html = response.read() 
	html = html.decode("utf-8") 
	print(html) 
	

User Agent
浏览器就是互联网世界上公认被允许的身份,如果我们希望我们的爬虫程序更像一个真实用户,那我们第一步,就是需要伪装成一个被公认的浏览器。用不同的浏览器在发送请求的时候,会有不同的 User-Agent 头。中文名为用户代理,简称UAUser Agent存放于Headers中 ,服务器就是通过查看Headers中的User Agent来判断是谁在访问,urllib中默认的User Agent,会有Python的字样,如果服务器检查User Agent,可以拒绝Python程序访问网站。
常见浏览器 User-Agent: https://blog.csdn.net/Kwoky/article/details/80381246

设置User Agent
方法 1、在创建 Request 对象的时候,填入 headers 参数(包含 User Agent 信息),这个Headers参数要求为字典。

方法2、:在创建Request对象的时候不添加headers参数,在创建完成之后,使用add_header()的方法,添加headers

代码:

from urllib import request 


if __name__ == "__main__": 
	#以 CSDN 为例,CSDN 不更改 User Agent 是无法访问的 
	url = 'http://www.csdn.net/' 
	head = {} 
	#写入 User Agent 信息 
	head['User-Agent'] = 'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166  Safari/535.19' 
	#创建 Request 对象 
	req = request.Request(url, headers=head) 
	# 也可以通过调用 Request.add_header() 添加/修改一个特定的 header 
	# req.add_header("User-Agent", "Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166  Safari/535.19") 
	req.add_header("Connection", "keep-alive") 
	# 也可以通过调用 Request.get_header()来查看 header 信息 
	print(req.get_header(header_name="Connection")) 
	print(req.get_header(header_name="User-Agent")) 
	#传入创建好的 Request 对象 
	response = request.urlopen(req) 
	#读取响应信息并解码 
	html = response.read().decode('utf-8') 
	#打印信息 
	print(html) 
	

IP代理
使用ip代理之后访问网站,可避免本机的ip 暴露:

代理分类 ,代理可以分为三种,即高度匿名代理、普通匿名代理和透明代理。

1、高度匿名代理 :隐藏客户的真实IP,但是不改变客户机的请求,就像有个真正的客户浏览器在访问服务器。
2、普通匿名代理 :能隐藏客户机的真实 IP,会改变客户的请求信息,服务器端不知道你的 ip地址但有可能认为我们使用了代理。
3、透明代理 :不但改变了我们的请求信息,还会传送真实的IP地址。

爬虫程序运行速度是很快,在网站爬取数据时,一个固定IP的访问频率就会很高,这不符合人为操作的标准。所以一些网站会设置一个IP访问频率的阈值,如果一个IP访问频率超过这个阈值,说明这个不是人在访问,而是一个爬虫程序。

解决办法一: 设置延时 。
解决办法二:使用 IP 代理。可以设置一些代理服务器,每隔一段时间换一个代理,就算 IP被禁止,依然可以换个IP继续爬取。
免费短期代理网站举例:
1、西刺免费代理IP http://www.xicidaili.com/
2、快代理免费代理 http://www.kuaidaili.com/free/inha/
3、聚合数据 https://www.juhe.cn/docs/api/id/62

代理IP选取
西刺网站为例,选出信号好的IP

使用代理的步骤:
1、调用urlib.request.ProxyHandler(),构建处理器对象,proxies参数为一个字典。

 class urllib.request.ProxyHandler(proxy=None) 

2、创建Opener对象

 urllib.request.build_opener([handler,...]) 

3、安装Opener

 urllib.request.install_opener(opener) 

使用 install_opener 方法之后,会将程序默认的 urlopen 方法替换掉。也就是说,如果使用install_opener之后,在该文件中,再次调用urlopen会使用自己创建好的opener

from urllib import request 


if __name__ == "__main__": 
	# 访问网址 
	# url = 'http://www.baidu.com/' 
	url='http://ip.27399.com/’ 
	# 这是代理 IP 
	proxy = {'http':'113.92.156.185:808'} 
	# 创建 ProxyHandler 
	proxy_support = request.ProxyHandler(proxy) 
	opener = request.build_opener(proxy_support) 
	# 添加 User Angent 
	opener.addheaders = [('User-Agent','Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36')] 
	# 安装 OPener 
	request.install_opener(opener) 
	# 使用自己安装好的 Opener 
	response = request.urlopen(url) 
	# 读取相应信息并解码 
	html = response.read().decode("utf-8") 
	#打印信息 
	print(html) 
	
	

url编码解码
urllib.parse.urlencode()函数帮我们将key:value这样的键值对转换成"key=value"这样的的字符串,解码工作可以使用urllib的unquote()函数。

from urllib import parse 


word = {"title" : "天猫商城"} 
url1 = parse.urlencode(word) 
print(url1) 
url2 =parse.unquote(url1) 
(url1) 

GET请求
GET 请求一般用于向服务器获取数据 ,案例:

from urllib import request 
from urllib import parse 
import chardet 


url = "http://www.baidu.com/s" 
word = {"wd":"端午节"} 
# 转换成 url 编码格式(字符串) 
word = parse.urlencode(word) 
# url 首个分隔符就是 ? 
newurl = url + "?" + word
headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"} 
req = request.Request(newurl, headers=headers) 
response = request.urlopen(req) 
html = response.read() 
charset = chardet.detect(html)['encoding'] 
print(charset) 
print(html.decode(charset)) 


POST请求
urlopendata参数,是POST方法进行Request请求时,要传送给服务器的数据,字典类型,里面要匹配键值对。
如果没有设置urlopen()函数的data参数,HTTP请求采用GET方式 。
使用urllib.parse.urlencode()函数将发送的表单数据编码 。

案例:向有道翻译发送data,得到翻译结果 。

from urllib import request 
from urllib import parse 
import json 


if __name__ == "__main__": 
	# 对应上图的 Request URL  为避免{"errorCode":50}的错误,去除 url 中的_o 
	 # Request_URL = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule' 
	 Request_URL = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule' 
	 # 创建 Form_Data 字典,存储上图的 Form Data 
	 Form_Data = {} 
	 Form_Data['i'] = 'Tom' 
	 Form_Data['from'] = 'AUTO' 
	 Form_Data['to'] = 'AUTO' 
	 Form_Data['smartresult'] = 'dict' 
	 Form_Data['client'] = 'fanyideskweb' 
	 Form_Data['salt'] = '1526796477689' 
	 Form_Data['sign'] = 'd0a17aa2a8b0bb831769bd9ce27d28bd' 
	 Form_Data['doctype'] = 'json' 
	 Form_Data['version'] = '2.1' 
	 Form_Data['keyfrom'] = 'fanyi.web' 
	 Form_Data['action'] = 'FY_BY_REALTIME' 
	 Form_Data['typoResult'] = 'false' 
	 # 使用 urlencode 方法转换标准格式 
	 data = parse.urlencode(Form_Data).encode('utf-8') 
	 head = {} 
	 # 写入 User Agent 信息 
	 head['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36' 
	  # 创建 Request 对象 
	  req = request.Request(Request_URL, headers=head) 
	  # 传递 Request 对象和转换完格式的数据   
	  response = request.urlopen(req,data=data) 
	  # 读取信息并解码 
	  html = response.read().decode('utf-8') 
	  # 使用 JSON 
	  translate_results = json.loads(html) 
	  # 找到翻译结果 
	  translate_results = translate_results['translateResult'][0][0]['tgt'] 
	  # 打印翻译信息 
	  print("翻译的结果是:%s" % translate_results) 
	  
	  
	 

Cookie
HTTP是无状态的面向连接的协议, 为了保持连接状态, 引入了Cookie机制, 在浏览器中存储用户信息 。
应用:Cookie模拟登陆

获取一个有登录信息的 Cookie 模拟登陆

from urllib import request 
import chardet 


# 1. 构建一个已经登录过的用户的 headers 信息 
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",   "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 
# 便于终端阅读,表示不支持压缩文件 
"Accept-Language":"zh-CN,zh;q=0.9", 
"Cache-Control": "max-age=0", 
"Connection":"keep-alive", 
 # 重点:这个 Cookie 是保存了密码无需重复登录的用户的 Cookie,这个 Cookie 里记录 了用户名,密码(通常经过 RAS 加密) 
 "Cookie": "__cfduid=d813c9add816556c64a8c087554cfb7af1508468882; BDUSS=kM2UnphaUpJRVphdjFrQ3R0TX5KM1NhY25mLVFmdTUtbTJ2ZndiMkw1TWRYRkJiQUFBQ UFBJCQAAAAAAAAAAAEAAABUN0cMVG9temt5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3PKFsdzyhba; BAIDUID=675B04E847A8A586ECC76203C511EA12:FG=1; PSTM=1529894757; BD_UPN=12314753; BIDUPSID=269D2DF8A150308A1A953FED45517BA8; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BD_CK_SAM=1; PSINO=1; H_PS_PSSID=1428_21106_20927; BD_HOME=1", 
 "Host":"www.baidu.com", 
 "Upgrade-Insecure-Requests":"1", 
 } 
# 2. 通过 headers 里的报头信息(主要是 Cookie 信息),构建 Request 对象 
req = request.Request("https://www.baidu.com/", headers = headers) 
# 3. 直接访问 renren 主页,服务器会根据 headers 报头信息(主要是 Cookie 信息),判断这 是一个已经登录的用户,并返回相应的页面 
response = request.urlopen(req) 
# 4. 打印响应内容 
html = response.read() 
charset = chardet.detect(html)['encoding'] 
print(charset) 
print(html.decode(charset)) 


cookielib库 和 HTTPCookieProcessor处理器
Python 处理 Cookie,一般是通过 cookielib 模块和 urllibrequest 模块的HTTPCookieProcessor处理器类一起使用。

cookielib模块:主要作用是提供用于存储cookie的对象 。

HTTPCookieProcessor处理器:主要处理cookie对象,并构建handler对象。

cookielib
主要作用是提供用于存储cookie的对象 。
该模块主要的对象有CookieJarFileCookieJarMozillaCookieJarLWPCookieJar

CookieJar:管理HTTP cookie值、存储HTTP请求生成的cookie、向传出的HTTP请求添加cookie 的对象。整个 cookie 都存储在内存中。

FileCookieJar (filename,delayload=None,policy=None)CookieJar 派生而来,将 cookie 存储到 文件中。filename 是存储 cookie 的文件名。delayloadTrue 时支持延迟访问文件,即只有 在需要时才读取文件或在文件中存储数据。

MozillaCookieJar (filename,delayload=None,policy=None) :从 FileCookieJar 派 生 而 来 , MozillaCookieJar 实例与 Mozilla 浏览器 cookies.txt 兼容。

LWPCookieJar (filename,delayload=None,policy=None):从 FileCookieJar 派生而来,实例与 libwww-perl 标准的 Set-Cookie3 文件格式兼容。

HTTPCookieProcessor处理器:处理cookie对象,并构建handler处理器对象。

案例:获取Cookie,生成CookieJar()对象中 。

from urllib import request 
import http.cookiejar 


# 构建一个 CookieJar 对象实例来保存 cookie 
cookiejar = http.cookiejar.CookieJar() 

# 使用 HTTPCookieProcessor()来创建 cookie 处理器对象,参数为 CookieJar()对象 
handler=request.HTTPCookieProcessor(cookiejar) 
# 通过 build_opener() 来构建 opener 
opener = request.build_opener(handler) 
# 4. 以 get 方法访问页面,访问之后会自动保存 cookie 到 cookiejar 中 
opener.open("https://www.baidu.com") 
# 可以按标准格式将保存的 Cookie 打印出来 
cookieStr = "" 
for item in cookiejar: 
	cookieStr = cookieStr + item.name + "=" + item.value + ";" 
# 舍去最后一位的分号 
print(cookieStr[:-1]) 




案例:获得网站cookie,保存在cookie文件中 。

import http.cookiejar 
from urllib import request 


# 保存 cookie 的本地磁盘文件名 
filename = 'cookie.txt' 

#1. 声明一个 MozillaCookieJar(有 save 实现)对象实例来保存 cookie,之后写入文件 
cookiejar = http.cookiejar.MozillaCookieJar(filename)
#2. 使用 HTTPCookieProcessor()来创建 cookie 处理器对象,参数为 CookieJar()对象 
handler = request.HTTPCookieProcessor(cookiejar) 
#3. 通过 build_opener() 来构建 opener 
opener = request.build_opener(handler) 
#4. 创建一个请求,原理同 urllib2 的 urlopen 
response = opener.open("http://www.baidu.com") 
#5. 保存 cookie 到本地文件 
cookiejar.save() 


案例:从文件中获取cookies,做为请求的一部分 。

from urllib import request 
import http.cookiejar 
import chardet 


# 创建 MozillaCookieJar(有 load 实现)实例对象 
cookiejar = http.cookiejar.MozillaCookieJar() 
# 从文件中读取 cookie 内容到变量 
cookiejar.load('cookie.txt') 
# 使用 HTTPCookieProcessor()来创建 cookie 处理器对象,参数为 CookieJar()对象 
handler = request.HTTPCookieProcessor(cookiejar) 
#通过 build_opener() 来构建 opener 
opener = request.build_opener(handler) 
response = opener.open("https://www.baidu.com") 
# 4. 打印响应内容 
html = response.read() 
charset = chardet.detect(html)['encoding'] 
print(charset) 
print(html.decode(charset)) 


案例:利用cookielibpost登录人人网

from urllib import request 
from urllib import parse 
import http.cookiejar 


# 1. 构建一个 CookieJar 对象实例来保存 cookie 
cookie = http.cookiejar.CookieJar() 
# 2. 使用 HTTPCookieProcessor()来创建 cookie 处理器对象,参数为 CookieJar()对象 
cookie_handler = request.HTTPCookieProcessor(cookie) 
# 3. 通过 build_opener() 来构建 opener 
opener = request.build_opener(cookie_handler) 
# 4. addheaders 接受一个列表,里面每个元素都是一个 headers 信息的元祖, opener 将附带 headers 信息 
opener.addheaders = [("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36")] 
# 5. 需要登录的账户和密码 
data = {"email":"123@163.com", "password":"123"} 
# 6. 通过 urlencode()转码 
postdata = parse.urlencode(data).encode(encoding='UTF8') 
print(postdata) 
# 7. 构建 Request 请求对象,包含需要发送的用户名和密码 
req = request.Request("http://www.renren.com/PLogin.do", data = postdata) 
# 8. 通过 opener 发送这个请求,并获取登录后的 Cookie 值, 
opener.open(req) 
# 9. opener 包含用户登录后的 Cookie 值,可以直接访问那些登录后才可以访问的页面 
response = opener.open("http://www.renren.com/966745694/profile") 
# 10. 打印响应内容 
print(response.read().decode()) 





获取AJAX加载的内容
AJAX一般返回的是JSON,直接对AJAX地址进行postget,就返回JSON数据了。

from urllib import request 
from urllib import parse


url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action" 
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36"} 
# 变动的是这两个参数,从 start 开始往后显示 limit 个 
formdata = {'start':'0',  'limit':'10' }
data = parse.urlencode(formdata).encode(encoding='UTF8') 
req = request.Request(url, data = data, headers = headers) 
response = request.urlopen(req) 
print(response.read().decode('utf-8')) 


HTTPS请求 SSL证书验证
现在随处可见 https 开头的网站,urllib2 可以为 HTTPS 请求验证 SSL 证书,就像 web浏览器一样,如果网站的 SSL 证书是经过 CA 认证的,则能够正常访问,如:https://www.baidu.com/等…

如果 SSL 证书验证不通过,或者操作系统不信任服务器的安全证书,比如浏览器在访问12306 网站如:https://www.12306.cn/mormhweb/的时候,会警告用户证书不受信任。

urllib在访问:

from urllib import request 


url = "https://www.12306.cn/mormhweb/" 
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"} 
req = request.Request(url, headers = headers) 
response = request.urlopen(req) 
print(response.read()) 

会报出SSLError
如果以后遇到这种网站,我们需要单独处理 SSL 证书,让程序忽略 SSL 证书验证错误,即可正常访问。

from urllib import request 
# 1. 导入 Python SSL 处理模块 
import ssl 


# 2. 表示忽略未经核实的 SSL 证书认证 
context = ssl._create_unverified_context() 
url = "https://www.12306.cn/mormhweb/" 
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"} 
req = request.Request(url, headers = headers) 
response = request.urlopen(req,context=context) 
print(response.read().decode('utf8')) 



URLError
urllib.error可以接收有urllib.request产生的异常。
产生的原因主要有:
1、没有网络连接
2、服务器连接失败
3、找不到指定的服务器

HTTPError
HTTPErrorURLError 的子类,我们发出一个请求时,服务器上都会对应一个 response应答对象,其中它包含一个数字"响应状态码"

如果 urlopen 不能处理的,会产生一个 HTTPError,对应相应的状态码,HTTP 状态码表示HTTP协议所返回的响应的状态。

混合使用
如果想用 HTTPErrorURLError 一起捕获异常,那么需要将 HTTPError 放在 URLError的前面,因为HTTPErrorURLError的一个子类。如果URLError放在前面,出现HTTP异常会先响应URLError,这样HTTPError就捕获不到错误信息了。

from urllib import request 
from urllib import error 


req = request.Request("http://www.douyu.com/tom_kwok.html") 
try: 
	request.urlopen(req) 
except error.HTTPError as err: 
	print(err.code) 
except error.URLError as err: 
	print(err) 
else: 
	print("Good Job") 
	

状态码 :
状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值:
1xx:指示信息–表示请求已接收,继续处理
2xx:成功–表示请求已被成功接收、理解、接受
3xx:重定向–要完成请求必须进行更进一步的操作
4xx:客户端错误–请求有语法错误或请求无法实现
5xx:服务器端错误–服务器未能实现合法的请求
常见状态代码、状态描述、说明:
200 OK //客户端请求成功
400 Bad Request //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized //请求未经授权,这个状态代码必须和 WWW-Authenticate 报头域一起使用
403 Forbidden //服务器收到请求,但是拒绝提供服务
404 Not Found //请求资源不存在,eg:输入了错误的 URL
500 Internal Server Error //服务器发生不可预期的错误
503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值