2.1 Python使用Urllib库爬取数据

Urllib是Python自带的库,麻雀虽小五脏俱全,可以利用这个库完成网站的简单爬虫应用。本文为学习崔庆才的gitbookUrllib官网总结输出。

其中最主要的三个模块如下:

  • 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 模块中定义的异常。主要包含URLErrorHTTPError

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