urllib 源码小剖
urllib 源码小剖
urllib 是 python 内置的网络爬虫模块,如果熟悉 python 一定能很快上手使用 urllib。
写这篇文章的目的是因为用到了它,但因为用的次数较多,又或者是具体的需求,有必要深入去理解内部的工作方式。
urllib 最简单的使用,我也从下面的语句中开始:
1
2
3
4
|
import urllib params = urllib.urlencode({ 'spam' : 1 , 'eggs' : 2 , 'bacon' : 0 }) print f.read() |
urllib 是模块,urlopen 是模块中的一个方法,它应该属于最高层的封装了,对于传入的任意 url 都能够处理,不管是 http还是https,还是 ftp 还是 file(本地文件).
它返回一个文件对象的包装类,里面除了文件对象,还有 HTTP response 的头和状态码,url 等;根据网络环境或者服务响应速度,会延迟一些时间。
注意,在这个时候,网络上的资源已经读取到了本地,被放在一个文件中。
接下来,f.read 从文件对象中读取数据。
下面是 urlopen 的源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
def urlopen(url, data = None , proxies = None ): ...... global _urlopener if proxies is not None : opener = FancyURLopener(proxies = proxies) elif not _urlopener: opener = FancyURLopener() _urlopener = opener else : opener = _urlopener if data is None : return opener. open (url) else : return opener. open (url, data) |
其中,我们可以得到的讯息是,它创建了类 FancyURLopener 对象,并调用了它的 open方法,而类 FancyURLopener 就是 urllib 的核心。
FancyURLopener 其实是 URLopener 的子类,所以从 URLopener 开始说起。
__tempfiles 是一个 list,用来存储从网络爬取到本地的本地文件名,你可以单独调用这个方法
addheader 添加 HTTP 头,得到了一个 URLopener 对象,就可以使用此函数添加额外的 HTTP 头
open 上面已经提到的,它相当于一个工程老板,会根据不同的 url 来为不同的部门派发不同任务,比如,提供的是 http://baidu.com 就会调用 open_http
open_unknown 无法解析的 url就会调用它,抛出异常
retrieve 爬取网络资源,存储在本地文件,返回一个本地文件的文件名和 HTTP 的response 头
open_http 上面提到过,很综合的处理函数,可以提供 HTTP 基本访问认证,proxy 认证等功能,调用 httplib库的函数。在得到 HTTP response后,会根据 HTTP status 状态码返回爬取的结果或者调用 error 处理函数 http_error
http_error 它其实也是个老板,会根据不同的状态码,为不同的部门分发不同的任务,比如,302 状态码就会调用 http_error_302 方法,302 是资源被临时迁移了,所以会发起再次的请求。
http_error_default 抛出异常,当懒得理那些毛毛小小的错误,就会使用这样的函数
open_https 提供 https 的爬取,和 open_http 差不多
open_file 爬取 ftp 或者直接读取本地文件
open_local_file open_file 当需要直接读取本地文件时候会调用此函数
open_ftp open_file 当 ftp 资源时候会调用此函数
open_data 好似官方没怎么介绍,应该可以忽略它
FancyURLopener 是 urlopener 的子类,主要提供了更详细的错误处理
http_error_302 302 状态码的处理
redirect_internal 302 里边调用这个
http_error_301 直接调用302
http_error_303 直接调用302
http_error_307 当是 POST 的时候,调用直接调用 http_error_default;其他调用 http_error_default
http_error_401 是认证处理
http_error_407 是认证处理,但需要 proxy 代理
retry_proxy_http_basic_auth 代理重新认证 401 的时候会用到
retry_proxy_https_basic_auth 同上
retry_http_basic_auth 访问认证
retry_https_basic_auth 同上
prompt_user_passwd 认证的时候需要账号密码,控制台输入
关于 HTTP 协议的基本认证,推荐阅读:HTTP://www.cnblogs.com/TankXiao/archive/2012/09/26/2695955.html 简单明了
从上面可以看出,无论是 urlopener 还是 FancyURLopener 都没有涉及具体的 ftp 操作,因为在 urllib 中有为 ftp 提供封装:class ftpwrapper 在 open_ftp 中会直接创建 ftpwrapper 对象,然后执行其内部操作。
具体不叙述了。
class addbase 主要包装对文件对象的操作 read close 等
class addinfo addbase 的子类,添加了返回 HTTP response 头方法
class addinfourl addinfo 的子类,添加返回 url 方法
print f.read() 这一句调用其实就是 文件对象的 read,但它是 addinfourl 对象
接下来就是一些实用的工具函数了,主要处理各式各样的 url,譬如提取url里面的 host,port等。源码里有各种实用方法的效果图:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# Utilities to parse URLs (most of these return None for missing parts): # unwrap('<URL:type://host/path>') --> 'type://host/path' # splittype('type:opaquestring') --> 'type', 'opaquestring' # splithost('//host[:port]/path') --> 'host[:port]', '/path' # splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]' # splitpasswd('user:passwd') -> 'user', 'passwd' # splitport('host:port') --> 'host', 'port' # splitquery('/path?query') --> '/path', 'query' # splittag('/path#tag') --> '/path', 'tag' # splitattr('/path;attr1=value1;attr2=value2;...') -> # '/path', ['attr1=value1', 'attr2=value2', ...] # splitvalue('attr=value') --> 'attr', 'value' # unquote('abc%20def') -> 'abc def' # quote('abc def') -> 'abc%20def') |
最后总结,urlopen 是最高层的封装,简单的一句话就可以爬取 WWW 很简单;其内部是通由 FancyURLopener 实现,FancyURLopener 是 URLopener 的父类:URLopener 实现了爬取方法,但未定义对应具体状态码的 error handlers,这些由 FancyURLopener 定义。
捣乱 2013-08-25
urllib 源码小剖的更多相关文章
- urllib2 源码小剖
urllib2 源码小剖 2013-08-25 23:38 by 捣乱小子, 272 阅读, 0 评论, 收藏, 编辑 两篇小剖已经完成: urllib 源码小剖 urllib2 源码小剖 urlli ...
- Django 源码小剖: 响应数据 response 的返回
响应数据的返回 在 WSGIHandler.__call__(self, environ, start_response) 方法调用了 WSGIHandler.get_response() 方法, 由 ...
- Django 源码小剖: 初探 WSGI
Django 源码小剖: 初探 WSGI python 作为一种脚本语言, 已经逐渐大量用于 web 后台开发中, 而基于 python 的 web 应用程序框架也越来越多, Bottle, Djan ...
- Django 源码小剖: 初探中间件(middleware)
因为考虑到文章的长度, 所以 BaseHandler 的展开被推迟了. 在 BaseHandler 中隐藏着中间件的信息, 较常见的 SessionMiddleware 就已经默认安装. BaseH ...
- Django 源码小剖: Django 对象关系映射(ORM)
引 从前面已经知道, 一个 request 的到来和一个对应 response 的返回的流程, 数据处理和数据库离不开. 我们也经常在 views.py 的函数定义中与数据库打交道. django O ...
- Django 源码小剖: Django 中的 WSGI
Django 其内部已经自带了一个方便本地测试的小服务器, 所以在刚开始学习 Django 的时候并不需搭建 apache 或者 nginx 服务器. Django 自带的服务器基于 python w ...
- Django 源码小剖: Django ORM 查询管理器
ORM 查询管理器 对于 ORM 定义: 对象关系映射, Object Relational Mapping, ORM, 是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换.从 ...
- Django 源码小剖: 更高效的 URL 调度器(URL dispatcher)
效率问题 django 内部的 url 调度机制说白了就是给一张有关匹配信息的表, 这张表中有着 url -> action 的映射, 当请求到来的时候, 一个一个(遍历)去匹配. 中, 则调用 ...
- Django 源码小剖: URL 调度器(URL dispatcher)
在刚开始接触 django 的时候, 我们尝试着从各种入门文档中创建一个自己的 django 项目, 需要在 mysite.urls.py 中配置 URL. 这是 django url 匹配处理机制的 ...
随机推荐
- CSharp设计模式读书笔记(17):迭代器模式(学习难度:★★★☆☆,使用频率:★★★★★)
迭代器模式(Iterator Pattern):提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标(Cursor). 模式角色与结构: 实现代码: using System; us ...
- 【高德地图API】从零开始学高德JS API(四)搜索服务——POI搜索|自动完成|输入提示|行政区域|交叉路口|自有数据检索
原文:[高德地图API]从零开始学高德JS API(四)搜索服务——POI搜索|自动完成|输入提示|行政区域|交叉路口|自有数据检索 摘要:地图服务,大家能想到哪些?POI搜素,输入提示,地址解析,公 ...
- [CLR via C#]1.4 执行程序集的代码
原文:[CLR via C#]1.4 执行程序集的代码 1. 托管程序集同时包含元数据和IL.IL是与CPU无关的机器语言.可将IL是为一种面向对象的机器语言. 2. IL也是能使用汇编语言来写的,M ...
- android详细信息java.util.ConcurrentModificationException变态
在今天做android当项目,我遇到了这个异常,好吧.其实最不寻常遇到异常IllegalstateException.它们与我们的硬件连接SDK抛出,我想折磨学生阿玉啊.扯远了. 今天,我想回到这个异 ...
- Atitit.软件GUIbutton与仪表盘--db数据库区--导入mysql sql错误的解决之道
Atitit.软件GUIbutton与仪表盘--db数据库区--导入mysql sql错误的解决之道 Keyword::截取文本文件后部分 查看提示max_allowed_packet限制 Targe ...
- 在打包程序中自动安装SQL Server数据库 .
原文:在打包程序中自动安装SQL Server数据库 . 1.创建安装项目“Setup1”安装项目 在“文件”菜单上指向“添加项目”,然后选择“新建项目”. 在“添加新项目”对话框中,选择“项目类型” ...
- sessionStorage、localStorage、cookie
sessionStorage 和 localStorage 是HTML5 Web Storage API 提供的,可以方便的在web请求之间保存数据.有了本地数据,就可以避免数据在浏览器和服务器间不必 ...
- EasyMonkeyDevice vs MonkeyDevice&HierarchyViewer API Mapping Matrix
1. 前言 本来这次文章的title是写成和前几篇类似的<EasyMonkeyDevice API实践全记录>,内容也打算把每个API的实践和建议给记录下来,但后来想了下觉得这样子并不是最 ...
- 快速构建Windows 8风格应用28-临时应用数据
原文:快速构建Windows 8风格应用28-临时应用数据 本篇博文主要介绍临时应用数据概览.如何构建临时应用数据. 一.临时应用数据概览 临时应用数据相当于网页中缓存,这些数据文件是不能够漫游的,并 ...
- NET Socket服务编程
smark https://github.com/IKende/ .NET Socket服务编程之-高效连接接入编 在.NET上编写网络服务深入都有2,3年了,而这些时间时如何在.NET里实现网络服务 ...