python爬虫(2)——urllib库


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对象,这是一个类文件句柄对象,它主要有以下几种方法:
    1. read(size):返回指定字节的数目,默认为全部
    2. readline():返回一行
    3. readlines():用列表返回全部行
    4. getcode():返回状态码,resp.getcode()等价于 resp.status
    5. 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库基本上就可以写一些比较简单的爬虫了,但这里我们想象中的那种强大的爬虫还是有些差距,所以还需要继续学习呀!


文章作者: Reset Ran
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Reset Ran !
  目录