2.1 Python使用Urllib库爬取数据
Urllib是Python自带的库,麻雀虽小五脏俱全,可以利用这个库完成网站的简单爬虫应用。本文为学习崔庆才的gitbook与Urllib官网总结输出。
其中最主要的三个模块如下:
urllib.request:第一个模块 request,它是最基本的 HTTP 请求模块,我们可以用它来模拟发送一请求,就像在浏览器里输入网址然后敲击回车一样,只需要给库方法传入 URL 还有额外的参数,就可以模拟实现这个过程了。
urllib.error:第二个 error 模块即异常处理模块,如果出现请求错误,我们可以捕获这些异常,然后进行重试或其他操作保证程序不会意外终止。
urllib.parse:第三个 parse 模块是一个工具模块,提供了许多 URL 处理方法,比如拆分、解析、合并等等的方法。
1. 使用urllib.request发送请求
urllib.request 模块定义了函数与类来打开URL,获取HTTP/HTTPS报文,进行基本的授权,重定向,获取Cookie等等。主要通过urlopen()与Request()函数来构造HTTP/HTTPS请求。
1.1 urlopen()函数的API
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)url: 可以是一个
string或者是一个Request对象。data:一般使用
POST方法向服务器提交数据时,可以指定该参数,一般是一个对象。timeout: 指定等待服务器响应时间。
cafile:使用SSL时指定CA文件。
capath: CA文件路径。
cadefault: 一般忽略该参数。
函数返回一个对象,可作为文本管理器,同时这个对象有一些诸如geturl(),info(),read(),getcode()之类的函数。
测试一下:
1.2 Request()函数
其实,Request是定义的一个类,Request()是该类的初始化定义对象的函数。
第一个 url 参数是请求 URL,这个是必传参数,其他的都是可选参数。
第二个 data 参数如果要传必须传 bytes(字节流)类型的,如果是一个字典,可以先用 urllib.parse 模块里的 urlencode() 编码。
第三个 headers 参数是一个字典,就是 Request Headers ,可以在构造 Request 时通过 headers 参数直接构造,也可以通过调用 Request 实例的 add_header() 方法来添加。一般通过修改 User-Agent 来伪装浏览器,默认的 User-Agent 是 Python-urllib,我们可以通过修改它来伪装浏览器,比如要伪装火狐浏览器或者Chrome浏览器。
第四个 origin_req_host 参数指的是请求方的 host 名称或者 IP 地址。
第五个 unverifiable 参数指的是这个请求是否是无法验证的,默认是False。意思就是说用户没有足够权限来选择接收这个请求的结果。例如我们请求一个 HTML 文档中的图片,但是我们没有自动抓取图像的权限,这时 unverifiable 的值就是 True。
第六个 method 参数是一个字符串,它用来指示请求使用的方法,比如GET,POST,PUT等等。
测试一下,即可正常打印出网页源代码:
1.3 urllib使用代理
需要先构建一个ProxyHandler的类, 随后将该类用于构建网页打开的opener的类,再在request中安装该opener.
代理格式是"http://112.25.41.136:80",如果要账号密码是"http://user:password@112.25.41.136:80".
1.4 urllib获取网站cookies
需要使用http.cookiejar模块构建CookieJar对象,然后用HTTPCookieProcessor 来构建一个 Handler.
2. 使用urllib处理异常
Urllib 的 error 模块定义了由 request 模块产生的异常。如果出现了问题,request 模块便会抛出 error 模块中定义的异常。主要包含URLError和HTTPError。
2.1 URLError
URLError 类来自 Urllib 库的 error 模块,它继承自 OSError 类,是 error 异常模块的基类,由 request 模块生的异常都可以通过捕获这个类来处理。
它具有一个属性reason,即返回错误的原因。例:
2.2 HTTPError
它是 URLError 的子类,专门用来处理 HTTP 请求错误,比如认证请求失败等等。
它有三个属性。
code,返回 HTTP Status Code,即状态码,比如 404 网页不存在,500 服务器内部错误等等。
reason,同父类一样,返回错误的原因。
headers,返回 Request Headers。
因为 URLError 是 HTTPError 的父类,所以我们可以先选择捕获子类的错误,可以输出 reason、code、headers 属性,然后再去捕获父类的错误,所以上述代码更好的写法如下:
这样我们就可以做到先捕获 HTTPError,获取它的错误状态码、原因、Headers 等详细信息。如果非 HTTPError,再捕获 URLError 异常,输出错误原因。最后用 else 来处理正常的逻辑,这是一个较好的异常处理写法。
3. 使用urllib解析链接
Urllib 库里还提供了 parse 这个模块,它定义了处理 URL 的标准接口,例如实现 URL 各部分的抽取,合并以及链接转换。它支持如下协议的 URL 处理:file、ftp、gopher、hdl、http、https、imap、mailto、 mms、news、nntp、prospero、rsync、rtsp、rtspu、sftp、shttp、 sip、sips、snews、svn、svn+ssh、telnet、wais。
3.1 urlparse()
urlparse() 方法可以实现 URL 的识别和分段,我们先用一个实例来感受一下:
在这里我们利用了 urlparse() 方法进行了一个 URL 的解析,首先输出了解析结果的类型,然后将结果也输出出来。
运行结果:
观察可以看到,返回结果是一个 ParseResult 类型的对象,它包含了六个部分,分别是 scheme、netloc、path、params、query、fragment。
观察一下实例的URL:
urlparse() 方法将其拆分成了六部分,大体观察可以发现,解析时有特定的分隔符,比如 :// 前面的就是 scheme,代表协议,第一个 / 前面便是 netloc,即域名,分号 ; 前面是 params,代表参数。
3.2 urlunparse()
有了 urlparse() 那相应地就有了它的对立方法 urlunparse()。
它接受的参数是一个可迭代对象,但是它的长度必须是 6,否则会抛出参数数量不足或者过多的问题。
先用一个实例感受一下:
参数 data 用了列表类型,当然你也可以用其他的类型如元组或者特定的数据结构。
运行结果如下:
这样我们就成功实现了 URL 的构造。
3.3 quote()
quote() 方法可以将内容转化为 URL 编码的格式,有时候 URL 中带有中文参数的时候可能导致乱码的问题,所以我们可以用这个方法将中文字符转化为 URL 编码,实例如下:
在这里我们声明了一个中文的搜索文字,然后用 quote() 方法对其进行 URL 编码,最后得到的结果如下:
这样我们就可以成功实现URL编码的转换。
3.4 unquote()
有了 quote() 方法当然还有 unquote() 方法,它可以进行 URL 解码,实例如下:
这是上面得到的 URL 编码后的结果,我们在这里利用 unquote() 方法进行还原,结果如下:
可以看到利用 unquote() 方法可以方便地实现解码。
Last updated