@qinian
2019-04-11T14:06:53.000000Z
字数 6759
阅读 1258
爬虫
爬虫所需要的功能,基本上在urllib中都能找到,学习这个标准库,可以更加深入的理解后面更加便利的requests库。
- 首先:
- 在Pytho2.x中使用import urllib2——-对应的,在Python3.x中会使用import urllib.request,urllib.error
- 在Pytho2.x中使用import urllib——-对应的,在Python3.x中会使用import urllib.request,urllib.error,urllib.parse
- 在Pytho2.x中使用import urlparse——-对应的,在Python3.x中会使用import urllib.parse
- 在Pytho2.x中使用import urlopen——-对应的,在Python3.x中会使用import urllib.request.urlopen
- 在Pytho2.x中使用import urlencode——-对应的,在Python3.x中会使用import urllib.parse.urlencode
- 在Pytho2.x中使用import urllib.quote——-对应的,在Python3.x中会使用import urllib.request.quote
- 在Pytho2.x中使用cookielib.CookieJar——-对应的,在Python3.x中会使用http.CookieJar
- 在Pytho2.x中使用urllib2.Request——-对应的,在Python3.x中会使用urllib.request.Request
urllib是Python自带的标准库,无需安装,直接可以用。
提供了如下功能:
- 网页请求大类(urllib.request)
- URL解析(urllib.parse)
- 代理和cookie设置
- 异常处理(urllib.error)
- robots.txt解析模块(urllib.robotparser)
1、urllib.request.urlopen (打开网页)
urlopen一般常用的有三个参数,它的参数如下:
1) r = urllib.requeset.urlopen(url,data,timeout)
2) url:链接格式:协议://主机名:[端口]/路径,(比如url=r"http://www.baidu.com/",有可能有转义字符可以加上r
3)data:附加参数 必须是字节流编码格式的内容(bytes类型),可通过bytes()函数转化,如果要传递这个参数,请求方式就不再是GET方式请求,而是POST方式
4)timeout: 超时 单位为秒
import urllibr = urllib.request.urlopen('http://www.google.com.hk/')datatLine = r.readline() #读取html页面的第一行data=r.read().decode('utf8') #读取全部f=open("./1.html","wb") # 网页保存在本地f.write(data)f.close()
urlopen返回对象提供方法:
read() , readline() ,readlines() , fileno() , close() :这些方法的使用方式与文件对象完全一样
info():返回一个httplib.HTTPMessage对象,表示远程服务器返回的头信息
getcode():返回Http状态码。如果是http请求,200请求成功完成;404网址未找到
geturl():返回请求的url
urllib.parse.urlencode(url),对关键字进行编码可使得urlopen能够识别,urlencode()的参数是kv字典型, 使用urllib.parse.unquote()对关键字进行解码
那么带传参的get请求:
#一般url http://www.baidu.com#带参数的url http://www.baidu.com/s?wd=北京# url带中文,一般不能被识别,需要编码wd={"wd":"北京“}url="http://www.baidu.com/s?"wdd=urllib.parse.urlencode(wd) #编码url=url+wddreq=urllib.request.Request(url)reponse=urllib.request.urlopen(req)
代码展示
import urlliburl = 'https://passport.cnblogs.com/user/signin?'post = {'username': 'xxx','password': 'xxxx'}postdata = urllib.parse.urlencode(post).encode('utf-8')req = urllib.request.Request(url, postdata) #提交表单r = urllib.request.urlopen(req)
我们在进行注册、登录等操作时,会通过POST表单传递信息
这时,我们需要分析页面结构,构建表单数据post,使用urlencode()进行编码处理,返回字符串,再指定’utf-8’的编码格式,这是因为POSTdata只能是bytes或者file object。最后通过Request()对象传递postdata,使用urlopen()发送请求。
2、1 urllib.request.Request
urlopen()方法可以实现最基本请求的发起,但这几个简单的参数并不足以 构建一个完整的请求,如果请求中需要加入headers(请求头)等信息模拟浏览器,我们就可以利用更强大的Request类来构建一个请求。
#用Request类构建了一个完整的请求,增加了headers等一些信息import urllib.requestimport urllib.parseurl = 'http://httpbin.org/post'# 构造一个请求头 headers 字典header = {'Host'='http://www.baidu.com','User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36','Accept':'*/*','Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2','Accept-Encoding': 'gzip, deflate','Referer': 'http://www.baidu.com' #表明自己来自哪里}dict = {'name':'Germey'}data = urllib.parse.urlencode(dict).encode('utf-8') #先编码POST信息。data参数如果要传必须传bytes(字节流)类型的,如果是一个字典,先用urllib.parse.urlencode()编码。request = urllib.request.Request(url = url,data = data,headers = header,method = 'POST')response = urllib.request.urlopen(request)html = response.read().decode('utf-8')print(html)
2、2 urllib.request.BaseHandler (cookie)
- HTTPDefaultErrorHandler 用于处理HTTP响应错误,错误都会抛出 HTTPError 类型的异常。
- HTTPRedirectHandler 用于处理重定向
- HTTPCookieProcessor 用于处理 Cookie 。
- ProxyHandler 用于设置代理,默认代理为空。
- HTTPPasswordMgr用于管理密码,它维护了用户名密码的表。
- HTTPBasicAuthHandler 用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题。
2、3 cookie的使用
获取Cookie保存到变量
import http.cookiejarimport urllib.request#使用http.cookiejar.CookieJar()创建CookieJar对象cookie = http.cookiejar.CookieJar()handler = urllib.request.HTTPCookieProcessor(cookie)#使用HTTPCookieProcessor创建cookie处理器,并以其为参数构建opener对象opener = urllib.request.build_opener(handler)#将opener安装为全局urllib.request.install_opener(opener)response = urllib.request.urlopen('http://www.baidu.com')#response = opener.open('http://www.baidu.com')for item in cookie:print 'Name = '+item.nameprint 'Value = '+item.value
首先我们必须声明一个 CookieJar 对象,接下来我们就需要利用 HTTPCookieProcessor 来构建一个 handler ,最后利用 build_opener 方法构建出 opener ,执行 open() 即可。
最后循环输出cookiejar
获取Cookie保存到本地
import cookielibimport urllib#设置保存cookie的文件,同级目录下的cookie.txtfilename = 'cookie.txt'#声明一个MozillaCookieJar对象实例来保存cookie,之后写入文件cookie = cookielib.MozillaCookieJar(filename)#利用urllib库的HTTPCookieProcessor对象来创建cookie处理器handler = urllib.request.HTTPCookieProcessor(cookie)#通过handler来构建openeropener = urllib.request.build_opener(handler)#创建一个请求,原理同urllib2的urlopenresponse = opener.open("http://www.baidu.com")#保存cookie到文件cookie.save(ignore_discard=True, ignore_expires=True)
从文件中获取Cookie并访问
mport cookielibimport urllib2#创建MozillaCookieJar实例对象cookie = cookielib.MozillaCookieJar()#从文件中读取cookie内容到变量cookie.load('cookie.txt', ignore_discard=True, ignore_expires=True)#创建请求的requestreq = urllib.request.Request("http://www.baidu.com")#利用urllib的build_opener方法创建一个openeropener = urllib.request.build_opener(urllib2.HTTPCookieProcessor(cookie))response = opener.open(req)print response.read()
import urllib.requestdef use_proxy(proxy_addr,url):#构建代理proxy=urllib.request.ProxyHandler({'http':proxy_addr})# 构建opener对象opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)# 安装到全局# urllib.request.install_opener(opener)# data=urllib.request.urlopen(url).read().decode('utf8') 以全局方式打开data=opener.open(url).read().decode('utf8') # 或者直接用句柄方式打开return dataproxy_addr='61.163.39.70:9999'data=use_proxy(proxy_addr,'http://www.baidu.com')print(len(data))## 异常处理以及日输出
- opener通常是build_opener()创建的opener对象。
- install_opener(opener) 安装opener作为urlopen()使用的全局URL opener
异常处理结构如下
try:# 要执行的代码print(...)except:#try代码块里的代码如果抛出异常了,该执行什么内容print(...)else:#try代码块里的代码如果没有跑出异常,就执行这里print(...)finally:#不管如何,finally里的代码,是总会执行的print(...)
URLerror产生原因:
- 1、网络未连接(即不能上网)
from urllib import request, errortry:r=request.urlopen('http://www.baidu.com')except error.URLError as e:print(e.reason)
- 2、访问页面不存(HTTPError)
客户端向服务器发送请求,如果成功地获得请求的资源,则返回的状态码为200,表示响应成功。如果请求的资源不存在, 则通常返回404错误。
from urllib imort request, errortry:response = request.urlopen('http://www.baodu.com')except error.HTTPError as e:print(e.reason, e.code, e.headers, sep='\n')else:print("Request Successfully')# 加入 hasattr属性提前对属性,进行判断原因from urllib import request,errortry:response=request.urlopen('http://blog.csdn.ne')except error.HTTPError as e:if hasattr(e,'code'):print('the server couldn\'t fulfill the request')print('Error code:',e.code)elif hasattr(e,'reason'):print('we failed to reach a server')print('Reason:',e.reason)else:print('no exception was raised')# everything is ok