Urllib库与URLError异常处理

来源:互联网 发布:单片机温度报警器程序 编辑:程序博客网 时间:2024/06/16 05:06

Urllib库

快速使用Urllib库爬取网页

import urllib.request   # 导入urllib.requestfile = urllib.request.urlopen("http://www.baidu.com")data = file.read()dataline = file.readline()print(data)fhandle = open(r"F:/study/code/python/Spider/1.html","wb")fhandle.write(data)fhandle.close()

读取内容有常见3种方式:

  1. file.read():读取文件的全部内容,交给一个字符串
  2. file.readlines():读取文件的全部内容,交给一个字符串列表,推荐使用
  3. file.readline():读取文件的一行内容

使用urllib.request.urlretrieve()函数

filename=urllib.request.urlretrieve("http://www.baidu.com","f://study//code//python//spider/2.html")urllib.request.urlcleanup() # 清除缓存信息

使用该方法会产生一些缓存信息,使用urllib.request.urlcleanup()可以清除缓存信息
其他常见方法:file为爬取的网页
1. file.infor():返回与当前环境有关的信息
2. file.getcode():返回爬取网页的状态码,200表示爬取成功,否则失败
3. file.geturl():获得爬取的地址
4. urllib.request.quote():对网址进行编码

浏览器的模拟——Headers属性

有时候爬取网页会出现403错误,这是因为网页为了防止别人恶意采集信息,进行了反爬虫的设置。
测试:

import urllib.requesturl = "https://www.amazon.cn/?tag=baidu250-23&hvadid={creative}&ref=pz_ic_22fvxh4dwf_e"file = urllib.request.urlopen(url)

输出异常:urllib.error.HTTPError: HTTP Error 503: Service Unavailable
解决:
1. 打开浏览器,按F12
2. 选择Network,查看Headers下的User-Agent信息
3. 复制字段信息,在代码中修改报头
这里写图片描述

解决方法一:build_opener()修改报头

import urllib.requesturl = "https://www.amazon.cn/?tag=baidu250-23&hvadid={creative}&ref=pz_ic_22fvxh4dwf_e"headers = ("User-Agent",  "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36")opener = urllib.request.build_opener()opener.addheaders = [headers]print(opener.open(url).read())

详解:
1. headers用来存放一个字典类型
2. urllibopen()不支持HTTP的高级功能,修改报头可以用urllib.request.build_opener()
3. 创建一个opener对象,添加headers,使用open方法打开,最后用read()方法读出数据

解决方法二:add_header()添加报头

req = urllib.request.Request(url)req.add_header("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36.36")print(urllib.request.urlopen(req).read())

超时设置

如果我们访问一个网页长时间未响应系统就会判断为超时,即无法打开该网页。通过设置timeout的值可以设置超时时间值

file = urllib.request.urlopen("http://www.baidu.com", timeout = 1) # 设置timeout为1秒

HTTP协议请求实战

HTTP协议请求主要分为6种类型
1. GET请求:通过URL网址直接传递信息,也可以通过表单进行传递,这些表单中的信息会自动转为URL链接中的数据
2. POST请求:向服务器提交数据,比如在登录时
3. PUT请求:请求服务器存储一个资源,通常要指定存储位置
4. DELETE请求:请求服务器删除一个资源
5. HEAD请求:请求获取对应HTTP的报头信息
6. OPTIONS请求:获得当前URL所支持的请求类型

GET请求分析

打开百度,原始的URL链接如下:

https://www.baidu.com/?tn=57095150_2_oem_dg

输入想要检索的关键字,如“hello”得到URL如下:

https://www.baidu.com/s?wd=hello&rsv_spt=1&rsv_iqid=0xd541cc94000016b0&issp=1&f=8&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=57095150_2_oem_dg&rsv_enter=1&rsv_sug3=10&rsv_sug1=1&rsv_sug7=100&rsv_sug2=0&inputT=98454&rsv_sug4=98455

将网址部分提取出来对比分析:
1. ie=utf-8
2. wd=hello
用GET请求的网址格式为:“http://www.baidu.com/s?wd=关键字”

import urllib.requestwd = input()url = "http://www.baidu.com/s?wd="+wdrequest = urllib.request.Request(url)data = urllib.request.urlopen(request)..read()file = open("c:/test/get.html","wb")file.write(data)file.close()print(data.read())

当关键词出现中文时,会出现如下错误

builtins.UnicodeEncodeError: 'ascii' codec can't encode characters in position 10-13: ordinal not in range(128)

使用urllib.request.quote()可以解决此编码问题

import urllib.requestwd = input()kd = urllib.request.quote(wd)url = "http://www.baidu.com/s?wd="+kdrequest = urllib.request.Request(url)data = urllib.request.urlopen(request).read()file = open("c:/test/get.html","wb")file.write(data)file.close()print(data)

使用GET请求的思路如下:

  1. 构建对应的URL地址,包含GET请求的字段名和字段内容
  2. 以对应的URL为参数,构建Request参数
  3. 通过urlopen()打开构建的Request对象
  4. 按需求进行后续操作,如读取网页内容,将内容写入文件等

POST请求分析

使用POST请求的思路如下:

这里写图片描述
分析网页源码中的form标签,发现有两个属性值,用字典的方式传入
{字段名1:字段值1,字段名2:字段值2}

import urllib.requestimport urllib.parseurl = "http://www.iqianyue.com/mypost/"postdata = urllib.parse.urlencode({"name:":"逍遥哥哥","pass":"asd456..."}).encode("utf-8")request = urllib.request.Request(url,postdata)request.add_header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36")data = urllib.request.urlopen(request).read()file = open("c:/test/post.html", "wb")file.write(data)file.close()
  1. 设置好URL链接
  2. 构建表单数据,并用urllib.parse.urlendcode对数据进行编码
  3. 创建Request对象,参数包括URL地址和要传入的数据
  4. 使用add_header()添加报头信息
  5. 使用urllib.request.urlopen()打开Request对象,完成信息传递
  6. 后续处理,如读取网页内容,将内容写到文件中

代理服务器设置

使用代理服务器设置可以解决IP被网站屏蔽的问题,在网上搜索代理服务器可以找到代理服务器地址
这里写图片描述

import urllib.requestproxy_address = "171.117.121.204:8080"url = "http://www.baidu.com"def use_proxy(proxy_address, url):    proxy = urllib.request.ProxyHandler({"http":proxy_address})    opener = urllib.request.build_opener(proxy, urllib.request.HTTPHandler)    urllib.request.install_opener(opener)    data = urllib.request.urlopen(url).read().decode("utf-8")data = use_proxy(proxy_address, url)print(len(data))

DebugLog实战

在运行程序的过程中,如果我们需要边运行边打印调试信息,可以开启DebugLog
思路如下:
1. 使用urll.b.request.HTTPHandler()和uellib.request.HTTPShandler()将debugleave设置为1
2. 使用urllib.request.build_opener()创建自定义的opener对象,并使用1中设置的值作为参数
3. 使用urllib.request.install_opener()创建全局默认的opener,这样在使用urlopen()的时候也会使用我们安装的opener对象
4. 进行后续操作

import urllib.requesthttphd = urllib.request.HTTPHandler(debuglevel=1)httpshd = urllib.request.HTTPSHandler(debuglevel=1)opener = urllib.request.build_opener(httphd, httpshd)urllib.request.install_opener(opener)data = urllib.request.urlopen("http://www.baidu.com")

异常处理神器——UrlError实战

在进行异常处理时,要用到try….except语句,try中执行代码,except中捕获异常信息

URLError

产生URLError错误的几种可能:

  1. 连接不上服务器
  2. 远程URL不存在
  3. 无网络
  4. 触发了HTTPError错误

常见状态码的含义

200:一切正常(OK)
301:重定向到新的URL,永久性(Moved Permanently)
302:重定向到临时URL,非永久性(Found)
304:请求的资源未更新(Not Modified)
400:非法请求(Bad Request)
401:请求未经授权(Unauthorized)
403:禁止访问(Forbidden)
404:没有找到对应界面Not Found)
500:服务器内部出现错误(Internal Server Error)
501:服务器不支持实现请求所需要的功能(Not Implemented)

HTTPError

HTTPError是URLError的子类,不能处理产生URLError错误的前三种原因,URLError不能完全替代HTTPError,如下代码:

import urllib.requestimport urllib.errortry:    urllib.request.urlopen("http://www.baidussssss.net")except urllib.error.URLError as e:    print(e.code)    print(e.reason)

会提示错误builtins.AttributeError: 'URLError' object has no attribute 'code'
修改后的代码应该先判断是否具有e.code和e.reason属性