[关闭]
@qinian 2019-04-11T14:06:53.000000Z 字数 6759 阅读 743

uril模块介绍

爬虫


爬虫所需要的功能,基本上在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包中urllib.request模块,使用这个模型进行网页请求)

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: 超时 单位为秒

1、1 get请求(urllib.request.urlopen)(普通get请求,只传入url)

  1. import urllib
  2. r = urllib.request.urlopen('http://www.google.com.hk/')
  3. datatLine = r.readline() #读取html页面的第一行
  4. data=r.read().decode('utf8') #读取全部
  5. f=open("./1.html","wb") # 网页保存在本地
  6. f.write(data)
  7. 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请求:

  1. #一般url http://www.baidu.com
  2. #带参数的url http://www.baidu.com/s?wd=北京
  3. # url带中文,一般不能被识别,需要编码
  4. wd={"wd":"北京“}
  5. url="http://www.baidu.com/s?"
  6. wdd=urllib.parse.urlencode(wd) #编码
  7. url=url+wdd
  8. req=urllib.request.Request(url)
  9. reponse=urllib.request.urlopen(req)

1、2 POST请求 (urllib.request.Request(url, postdata),将除了url之外的postdata的其他信息也封装进去)、

代码展示

  1. import urllib
  2. url = 'https://passport.cnblogs.com/user/signin?'
  3. post = {
  4. 'username': 'xxx',
  5. 'password': 'xxxx'
  6. }
  7. postdata = urllib.parse.urlencode(post).encode('utf-8')
  8. req = urllib.request.Request(url, postdata) #提交表单
  9. r = urllib.request.urlopen(req)

我们在进行注册、登录等操作时,会通过POST表单传递信息
这时,我们需要分析页面结构,构建表单数据post,使用urlencode()进行编码处理,返回字符串,再指定’utf-8’的编码格式,这是因为POSTdata只能是bytes或者file object。最后通过Request()对象传递postdata,使用urlopen()发送请求。

2、请求高级功能(除了封装post信息,还可以封装请求头

2、1 urllib.request.Request

urlopen()方法可以实现最基本请求的发起,但这几个简单的参数并不足以 构建一个完整的请求,如果请求中需要加入headers(请求头)等信息模拟浏览器,我们就可以利用更强大的Request类来构建一个请求。

  1. #用Request类构建了一个完整的请求,增加了headers等一些信息
  2. import urllib.request
  3. import urllib.parse
  4. url = 'http://httpbin.org/post'
  5. # 构造一个请求头 headers 字典
  6. header = {
  7. 'Host'='http://www.baidu.com',
  8. 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36',
  9. 'Accept':'*/*',
  10. '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',
  11. 'Accept-Encoding': 'gzip, deflate',
  12. 'Referer': 'http://www.baidu.com' #表明自己来自哪里
  13. }
  14. dict = {'name':'Germey'}
  15. data = urllib.parse.urlencode(dict).encode('utf-8') #先编码POST信息。data参数如果要传必须传bytes(字节流)类型的,如果是一个字典,先用urllib.parse.urlencode()编码。
  16. request = urllib.request.Request(url = url,data = data,headers = header,method = 'POST')
  17. response = urllib.request.urlopen(request)
  18. html = response.read().decode('utf-8')
  19. print(html)

2、2 urllib.request.BaseHandler (cookie)

2、3 cookie的使用

获取Cookie保存到变量

  1. import http.cookiejar
  2. import urllib.request
  3. #使用http.cookiejar.CookieJar()创建CookieJar对象
  4. cookie = http.cookiejar.CookieJar()
  5. handler = urllib.request.HTTPCookieProcessor(cookie)
  6. #使用HTTPCookieProcessor创建cookie处理器,并以其为参数构建opener对象
  7. opener = urllib.request.build_opener(handler)
  8. #将opener安装为全局
  9. urllib.request.install_opener(opener)
  10. response = urllib.request.urlopen('http://www.baidu.com')
  11. #response = opener.open('http://www.baidu.com')
  12. for item in cookie:
  13. print 'Name = '+item.name
  14. print 'Value = '+item.value

首先我们必须声明一个 CookieJar 对象,接下来我们就需要利用 HTTPCookieProcessor 来构建一个 handler ,最后利用 build_opener 方法构建出 opener ,执行 open() 即可。
最后循环输出cookiejar

获取Cookie保存到本地

  1. import cookielib
  2. import urllib
  3. #设置保存cookie的文件,同级目录下的cookie.txt
  4. filename = 'cookie.txt'
  5. #声明一个MozillaCookieJar对象实例来保存cookie,之后写入文件
  6. cookie = cookielib.MozillaCookieJar(filename)
  7. #利用urllib库的HTTPCookieProcessor对象来创建cookie处理器
  8. handler = urllib.request.HTTPCookieProcessor(cookie)
  9. #通过handler来构建opener
  10. opener = urllib.request.build_opener(handler)
  11. #创建一个请求,原理同urllib2的urlopen
  12. response = opener.open("http://www.baidu.com")
  13. #保存cookie到文件
  14. cookie.save(ignore_discard=True, ignore_expires=True)

从文件中获取Cookie并访问

  1. mport cookielib
  2. import urllib2
  3. #创建MozillaCookieJar实例对象
  4. cookie = cookielib.MozillaCookieJar()
  5. #从文件中读取cookie内容到变量
  6. cookie.load('cookie.txt', ignore_discard=True, ignore_expires=True)
  7. #创建请求的request
  8. req = urllib.request.Request("http://www.baidu.com")
  9. #利用urllib的build_opener方法创建一个opener
  10. opener = urllib.request.build_opener(urllib2.HTTPCookieProcessor(cookie))
  11. response = opener.open(req)
  12. print response.read()

代理服务器设置(注意调用多次时,需要使用全局代理)

  1. import urllib.request
  2. def use_proxy(proxy_addr,url):
  3. #构建代理
  4. proxy=urllib.request.ProxyHandler({'http':proxy_addr})
  5. # 构建opener对象
  6. opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)
  7. # 安装到全局
  8. # urllib.request.install_opener(opener)
  9. # data=urllib.request.urlopen(url).read().decode('utf8') 以全局方式打开
  10. data=opener.open(url).read().decode('utf8') # 或者直接用句柄方式打开
  11. return data
  12. proxy_addr='61.163.39.70:9999'
  13. data=use_proxy(proxy_addr,'http://www.baidu.com')
  14. print(len(data))
  15. ## 异常处理以及日输出
  • opener通常是build_opener()创建的opener对象。
  • install_opener(opener) 安装opener作为urlopen()使用的全局URL opener

异常处理

异常处理结构如下

  1. try:
  2. # 要执行的代码
  3. print(...)
  4. except:
  5. #try代码块里的代码如果抛出异常了,该执行什么内容
  6. print(...)
  7. else:
  8. #try代码块里的代码如果没有跑出异常,就执行这里
  9. print(...)
  10. finally:
  11. #不管如何,finally里的代码,是总会执行的
  12. print(...)

URLerror产生原因:

  • 1、网络未连接(即不能上网)
  1. from urllib import request, error
  2. try:
  3. r=request.urlopen('http://www.baidu.com')
  4. except error.URLError as e:
  5. print(e.reason)
  • 2、访问页面不存(HTTPError)

客户端向服务器发送请求,如果成功地获得请求的资源,则返回的状态码为200,表示响应成功。如果请求的资源不存在, 则通常返回404错误。

  1. from urllib imort request, error
  2. try:
  3. response = request.urlopen('http://www.baodu.com')
  4. except error.HTTPError as e:
  5. print(e.reason, e.code, e.headers, sep='\n')
  6. else:
  7. print("Request Successfully')
  8. # 加入 hasattr属性提前对属性,进行判断原因
  9. from urllib import request,error
  10. try:
  11. response=request.urlopen('http://blog.csdn.ne')
  12. except error.HTTPError as e:
  13. if hasattr(e,'code'):
  14. print('the server couldn\'t fulfill the request')
  15. print('Error code:',e.code)
  16. elif hasattr(e,'reason'):
  17. print('we failed to reach a server')
  18. print('Reason:',e.reason)
  19. else:
  20. print('no exception was raised')
  21. # everything is ok
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注