urllib库简介
urllib 库是 Python 中一个最基本的网络请求库。可以模拟浏览器的行为,向指定的服务器发 送一个请求,并可以保存服务器返回的数据。
urlopen函数
在python3的urllib
库中,所有和网络请求相关的方法,都被集成到urllib.request
模块下了,该函数的使用格式如下:
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
其中:
cafile、capath、cadefault
参数:用于实现可信任的 CA 证书的 HTTP 请求。(基本上很少用)
context
参数:实现 SSL 加密传输。(基本上很少用)
所以我们一般关注前面几个参数就可以了:
- URL:所请求的URL
- data:请求的data,如果设置了这个参数,请求会变为post请求
- 返回值:返回值是一个http.client.HTTPResponse对象,这是一个类文件句柄对象,它主要有以下几种方法:
- read(size):返回指定字节的数目,默认为全部
- readline():返回一行
- readlines():用列表返回全部行
- getcode():返回状态码,
resp.getcode()
等价于resp.status
- getheaders():返回响应头
下面来看一个例子:
from urllib import request
url="http://www.baidu.com"
resp=request.urlopen(url)
print(resp.read())
运行上面的程序,就会打印出百度首页的html源代码,见下图:
request.urlretrieve函数
这个文件可以很方便的将网页上的文件保存到本地,就比如保存百度首页:
from urllib import request
url="http://www.baidu.com"
request.urlretrieve(url,'baidu.html')
运行代码后,就会在代码文件同目录下生成我们所命名的文件,如图:
同理,也可以用此方法下载图片,以下载一张王者荣耀韩信的图片为例:
from urllib import request
#图片链接只需在网页中鼠标右键选择复制图像链接即可
url="https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1107967462,1249145194&fm=26&gp=0.jpg"
request.urlretrieve(url,"韩信.jpg")
运行后,我们就能看到所下载的图片:
打开看一下:
parse.urlencode函数和parse.parse_qs函数
用浏览器发送请求的时候,如果 url 中包含了中文或者其他特殊字符,那么浏览器会自动的给我们进行编码。而如果使用代码发送请求,那么就必须手动的进行编码,这时候就应该使用 urlencode 函数来实现。urlencode 可以把字典数据转换为 URL 编码的数据。示例代码如下:
from urllib import parse
dic1 = {'name': '张三','age' : '18','slogan' : "Hello world"}
dic2=parse.urlencode(dic1)
print(dic2)
#输出如下:
name=%E5%BC%A0%E4%B8%89&age=18&slogan=Hello+world
如果不经过编码,就用urlopen方法的话,会报错:
from urllib import request,parse
resp = request.urlopen('http://www.baidu.com/s?wd=刘德华')
#报错如下:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 30-32: ordinal not in range(128)
编码之后就可以了:
from urllib import request,parse
parms = {'wd':'刘德华'}
url = 'http://www.baidu.com/s'
query_string = parse.urlencode(parms)
print(query_string)
url = url+'?'+query_string
resp = request.urlopen(url)
print(resp.getcode())
#输出如下:
wd=%E5%88%98%E5%BE%B7%E5%8D%8E
200
parse.parse_qs函数就是将编码后的数据再转变回来的函数:
from urllib import parse
dic1 = {'name': '张三','age' : '18','slogan' : "Hello world"}
dic2=parse.urlencode(dic1)
print(dic2)
print(parse.parse_qs(dic2))
#输出如下:
name=%E5%BC%A0%E4%B8%89&age=18&slogan=Hello+world
{'name': ['张三'], 'age': ['18'], 'slogan': ['Hello world']}#注意返回的数据类型
parse.urlparse 和 parse.urlsplit 函数
有时候拿到一个 url,想要对这个 url 中的各个组成部分进行分割,那么这时候就可以使用
urlparse 或者是 urlsplit 来进行分割。示例代码如下:
from urllib import request,parse
url = 'http://www.baidu.com/s?username=zhiliao'
result1 = parse.urlsplit(url)
result2 = parse.urlparse(url)
print(result1)
print(result2)
结果如下图:
从图中可以看出:urlparse 和 urlsplit 基本上是一模一样的。唯一不一样的地方是,urlparse 里面多了一个 params 属性,而 urlsplit 没有这个 params 属性。如果将上面代码的url换一下就能看出区别:
from urllib import request,parse
url = 'http://www.baidu.com/s;hello?wd=python&username=abc#1'
result1 = parse.urlsplit(url)
result2 = parse.urlparse(url)
print(result1)
print(result2)
结果:
不过params属性很少用到,所以这两种方法基本可以视为相同
ProxyHandler 处理器(代理设置)
很多网站会检测某一段时间某个 IP 的访问次数(通过流量统计,系统日志等),如果访问次数多的不像正常人,它会禁止这个 IP 的访问。所以我们可以设置一些代理服务器,每隔一段时间换一个代理,就算 IP 被禁止,依然可以换个 IP 继续爬取。urllib 中通过 ProxyHandler 来设置使用代理服务器,下面代码说明如何使用自定义 opener来使用代理:
import urllib
url = 'http://httpbin.org/ip'
headers = {'User-Agent':"Mozilla/5.0 (Macintosh; U; Mac OS X Mach-O; enUS; rv:2.0a) Gecko/20040614 Firefox/3.0.0 "}
req = urllib.request.Request(url,headers=headers)
resp = urllib.request.urlopen(req,timeout = 5)
print(resp.read().decode())
handler = urllib.request.ProxyHandler({'http':'163.204.240.95:9999'})
opener = urllib.request.build_opener(handler)
resp = opener.open(url)
print(resp.read().decode())
运行结果如下图:
可以看出,我们的向目标服务器发送请求的ip地址已经变了,这样就能有效防止目标服务器封我们ip而导致爬虫无法完整运行。
ps:这个网址:http://httpbin.org/ip,能帮我们快速查询我们的ip地址,可以保存下来使用哦
常见的代理获取可以点这里去看看,可以使用免费的代理,当然体验肯定没有付费的代理来得好。
总结
小总结一下,用urllib库基本上就可以写一些比较简单的爬虫了,但这里我们想象中的那种强大的爬虫还是有些差距,所以还需要继续学习呀!