现在的位置: 首页 > 综合 > 正文

python urllib/urllib2应用         Python urllib2递归抓取某个网站下图片       

2013年05月04日 ⁄ 综合 ⁄ 共 11153字 ⁄ 字号 评论关闭

简介:
urllib2是python的一个获取url(Uniform Resource Locators,一致资源定址器)的模块。它用urlopen函数的模式供给了一个十分简明的接口。这使得用各式各样的协定获取url成为也许。它一同也提供了一个稍许庞杂的接口来安排常见的情形-如大致的认证,cookies,代办,EJB
和 without EJB
,等等。这些都是由叫做opener和handler的对象来办理的,xi.xihuanplaza.com

以下是获得url最容易的方法:

import urllib2
response = urllib2.urlopen('http://python.org/')
html = response.read()

诸多urlib2的运用都是如此容易(留神我们原先也能够用一个以”ftp:”"file:”等开端的url替代”HTTP”开端的url).然而,这篇教程的目标是阐释关于HTTP更庞杂的状况。HTTP建基于央求和响应(requests &responses )-客户端制作央求效力器回来响应。urlib2用代 表了你正在要求的HTTP request的Request对象反映了这些。用它最简单的模式,你产生了一个Request对象来确定指明你想要获得的url。调用urlopen函数对恳求的url归来一个respons对象。这个respons是一个像file的对象,这意味着你能用.read()函数操纵这个respon对象:

import urllib2

req = urllib2.Request('http://om/')

对于HTTP,Request对象准许你做两件分外的事:第一,你可以向服务器发送数据。第二,你可以向服务器发送分外的消息(metadata),这些信息可以是关于数据本身的,或者是关于这个恳求本身的–这些信息被当作HTTP头发送。让我们顺次看一下这些。

数据:
有时你想向一个URL发送数据(通常这些数据是代表一些CGI脚本或者其余的web利用)。对于HTTP,这平常叫做一个Post。当你发送一个你在网上填的form(表单)时,这通常是你的博览器所做的。并不是所有的Post请求都来自HTML表单,这些数据必要被以准绳的形式encode,然后作为一个数据参数传递给Request对象。Encoding是在urlib中完结的,而不是在urlib2中完毕的。

import urllib
import urllib2

url = 'http://om/cgi-bin/register.cgi'
values = {'name' : 'Michael Foord',
'location' : 'Northampton',co.coa.org.cn,
'language' : 'Python' }

data = urllib.urlencode(values)
req = urllib2.Request(url, data)
response = urllib2.urlopen(req)
the_page = response.read()

假使你不传递数据参数,urlib2使用了一个GET请求。一个GET请求和POST请求的不同之处在于POST请求平常拥有边界效应:它们以某种形式转变体系的形势。(譬如,通过网页设置一条号令运送一英担罐装牛肉到你家。)固然HTTP准绳清晰的解释Post时常发生边界效应,而get从不发生边界效应,但没有什么能遏止一个get请求建立边界效应,或一个Post请求没有任何边界效应。数据也能被url自己加密(Encoding)然后通过一个get请求发送出去。

这经过以下完成:
>>> import urllib2
>>> import urllib
>>> data = {}
>>> data['name'] = 'Somebody Here'
>>> data['location'] = 'Northampton'
>>> data['language'] = 'Python'
>>> url_values = urllib.urlencode(data)
>>> print url_values
name=Somebody+Here&language=Python&location=Northampton
>>> url = 'http://om/example.cgi'
>>> full_url = url + '?' + url_values
>>> data = urllib2.open(full_url)

头:
我们将会在此地议论一个特异的HTTP头,来解释怎么向你的HTTP恳求中参与头。
有一些网站不期望被某些过程浏览或者针对不同的博览器归来不同的版本。默认状况下,urlib2把自己辨认为Python-urllib/x.y(此地的 xy是python发行版的首要或次要的版本号,如, Python-urllib/2.5),这些可能会混同站点,或者完整不职业。博览器差异亲身的方法是穿过User-Agent头。当你产生一个 Request对象时,你可以参与一个头字典。接下来的这个例子和上面的要求一样,不过它把自己定义为IE的一个版本。

import urllib
import urllib2

url = 'http://om/cgi-bin/register.cgi'
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
values = {'name' : 'Michael Foord',
'location' : 'Northampton',
'language' : 'Python' }
headers = { 'User-Agent' : user_agent }

data = urllib.urlencode(values)
req = urllib2.Request(url, data, headers)
response = urllib2.urlopen(req)
the_page = response.read()

Respons同样有两种有用的措施。当我们出失误尔后,看一下关于info and geturl的局部。

异样解决:

不能解决一个respons时,urlopen抛出一个urlerror(固然像寻常一样对于python APIs,内建反常如,ValueError, TypeError 等也会被抛出。)
HTTPerror是HTTP URL在尤其的情形下被抛出的URLError的一个子类。
urlerror:
平常,urlerror被抛出是因为不曾网络衔接(没有至特定效劳器的联结)或许特定的效力器不存留。在这种情形下,含有reason属性的反常将被抛出,以一种包罗过错代码和文本差错消息的tuple模式。

e.g.
>>> req = urllib2.Request('http://ode>>> print e.read()>>>404...... etc

容错:
假使你预备安排HTTP谬误和URL讹谬此地有两种大体的计策,我更趋向于后一种:

1.
from urllib2 import Request, urlopen, URLError, HTTPError
req = Request(someurl)
try:
response = urlopen(req)
except HTTPError, e:
print 'The server couldn/'t fulfill the request.'
print 'Error code: ', e.code
except URLError, e:
print 'We failed to reach a server.'
print 'Reason: ', e.reason
else:
# everything is fine

注意:HTTP过错异样一定在前面,不然URL谬误也会捉拿一个HTTP过失。
2
from urllib2 import Request, urlopen, URLError
req = Request(someurl)
try:
response = urlopen(req)
except URLError, e:
if hasattr(e, 'reason'):
print 'We failed to reach a server.'
print 'Reason: ', e.reason
elif hasattr(e, 'code'):
print 'The server couldn/'t fulfill the request.'
print 'Error code: ', e.code
else:
# everything is fine

注意:URL过失是IO过错反常的一个子类。这意味着你能防止引入(import)URL差错而应用:

from urllib2 import Request, urlopen
req = Request(someurl)
try:
response = urlopen(req)
except IOError, e:
if hasattr(e, 'reason'):
print 'We failed to reach a server.'
print 'Reason: ', e.reason
elif hasattr(e, 'code'):
print 'The server couldn/'t fulfill the request.'
print 'Error code: ', e.code
else:
# everything is fine

极半点环境下,urllib2可以抛出socket.error.

INFO and GETURL
urlopen回来的response(或许HTTP差错实例)有两个有用的方式:info和geturl。

geturl–它归来被获取网页的真实的url。这是很有用的,因为urlopen(或使用的opener对象)可能会随同一个重定向。
获取的网页url可能和请求的网页url不一样。

info–它回来一个像字典的对象来刻画获取的网页,特别是效劳器发送的头,MySQL存储历程中运用事务。它目前平常是httplib.HTTPMessage的一个实例,PHP中的字符串函数
典范的头包括'Content-length', 'Content-type', 等等。看一下Quick Reference to HTTP Headers中,HTTP头列表,还有
关于他们容易的阐释和运用方式。
Openers 和Handlers
当你获取一个URL时,你使用一个opener(一个也许以一个对照昏乱名字命名的实例–urllib2.OpenerDirector)。正情理况下
我们始终使用默许的opener,穿过urlopen,但你也可以建设自定义的openers。opener使用操纵器(handlers)。所有的粗活都交给这些handlers来做。每一个handler知晓
怎么敞开url以一种特别的url协定(http,ftp等等),或者怎么办理敞开url的某些方面,如,HTTP重定向,或者HTTP cookie。

你将会建设openers万一你想要用装配尤其的handlers获取url,譬如,获取一个办理cookie的opener,或者一个不安排重定向的opener。

枚举一个OpenerDirector,然后多次调用.add_handler(some_handler_instance)来创立一个opener。
或许,你能够用build_opener,这是一个很适宜的创立opener对象的函数,它只有一个函数调用。build_opener默许会参与诸多
handlers,然而提供了一个迅速的措施增加更多东西和/或使默认的handler失效。
其余你想要的handlers可以办理代办,authentication和另外寻常然而又有些特异的状况。
install_opener能被用于建设一个opener对象,(整体)默认的opener。这意味着调用urlopen将会用到你刚装配的opener。
opener对象有一个open方式,它可以被直接调用来获取url以一种和urlopen函数同样的方法:不曾必需调用install_opener,除了是为了适宜。

Basic Authentication:(大致印证)

为打听释开创和安装一个handler,我们将会使用 HTTPBasicAuthHandler。更多关于这个东西的内容和翔实议论—包罗一个 Basic Authentication如何职业的讲述–参见 Basic Authentication Tutorial.

当必要Authentication的时候,效力器发送一个头(一同还有401代码)央求Authentication。它翔实指明了一个Authentication和一个域。这个头看起来像:

Www-authenticate: SCHEME realm=”REALM”.
e.g.
Www-authenticate: Basic realm=”cPanel Users”

客户端然后就会用包罗在头中的准确的帐户和密码从新要求这个域。这是”大致印证”。为了简化这个历程,我们能够创立一个
HTTPBasicAuthHandler和opener的实例来应用这个handler。
HTTPBasicAuthHandler用一个叫做密码管制的对象来解决url和用户名和密码的域的照射。万一你知晓域是什么(从效劳器发送的authentication
头中),那你就可以运用一个HTTPPasswordMgr。多数状况下人们不在意域是什么。那样应用HTTPPasswordMgrWithDefaultRealm就很适宜。它
准许你为一个url详细指定用户名和密码。这将会在你不曾为一个特异的域供给一个可供抉择的密码锁时提提供你。我们经过提供None作为add_password措施域的参数指出
这一点。
最高等别的url是必要authentication的第一个url。比你递送给.add_password()的url更深的url同样也会相称。

# create a password manager
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
# Add the username and password.
# If we knew the realm, we could use it instead of “None“.
top_level_url = “http://example.com/foo/”
password_mgr.add_password(None, top_level_url, username, password)

handler = urllib2.HTTPBasicAuthHandler(password_mgr)
# create “opener” (OpenerDirector instance)
opener = urllib2.build_opener(handler)
# use the opener to fetch a URL
opener.open(a_url)
# Install the opener.
# Now all calls to urllib2.urlopen use our opener.
urllib2.install_opener(opener)

留神:在以上的举例中我们只给build_opener供给了HTTPBasicAuthHandler。默许opener有对一般情形的操纵器(handlers)- ProxyHandler, UnknownHandler, HTTPHandler, HTTPDefaultErrorHandler, HTTPRedirectHandler, FTPHandler, FileHandler, HTTPErrorProcessor.
高等别url切实上是一个全面的url(包罗http:协定组件和主机名可选的端口号),如”http://example.com”或者是一个授权(同样,主机名,可选的端口号)
如”"example.com” 或 “example.com:8080″(后一个举例包括了一个端口号)。授权,万一被涌现,必定不能包罗用户消息-如”oe@password:example.com”
是不准确的、
代办:
urllib2将会主动检测你的代理安设并使用它们。这是经过 ProxyHandler完成的,它是操作器链的一局部。正情理况下,这是个好东西,然而也有它不那么有用的偶尔景况。
一个做这些的计策是装配我们自己的ProxyHandler,不必任何定义任何代理。使用一个和产生Basic Authentication操作器相仿的环节可以完成:

>>> proxy_support = urllib2.ProxyHandler({})
>>> opener = urllib2.build_opener(proxy_support)
>>> urllib2.install_opener(opener)
留神:
眼前urllib2不扶持穿过代理获取HTTPs位子。这是一个问题。
sockets和layers
python扶持获得层叠的网页的源码。urllib2使用httplib library,而httplib library反来到使用socket library。
对于python2.3你可以指明一个socket应当在超时之前期待response多久。这在这些不得不获取网页的利用中很有用。默认socket模块没有超时况且可以挂起。
眼前,socket超时在urllib2或者httplib水准中不可见。可是,你可以整体地为所有socket安设默认的超时。

import socket
import urllib2
# timeout in seconds
timeout = 10
socket.setdefaulttimeout(timeout)
# this call to urllib2.urlopen now uses the default timeout
# we have set in the socket module
req = urllib2.Request('http://om/han_life/blog/item/8677342693411504918f9d9b.html">http://hi.baidu.com/han_life/blog/item/8677342693411504918f9d9b.html

目前,Example对象具有负值了!假使getValues() 的调用者永久也不安设归来的Dimension对象的width 和height值,那么仅凭测验是不也许检测到这类的过失。

########################################

urllib模块提供的上层接口,使我们可以像读取本地文件一样读取www和ftp上的数据。
先看一个例子,这个例子把Google首页的html抓取下来并显示在控制台上:

import urllib
print urllib.urlopen('http://www.google.com').read()
urllib.urlopen(url[, data[, proxies]]) :
  创建一个表示远程url的类文件对象,然后像本地文件一样操作这个类文件对象来获取远程数据。参数url表示远程数据的路径,一般是网址;参数data表 示以post方式提交到url的数据(玩过web的人应该知道提交数据的两种方式:post与get。如果你不清楚,也不必太在意,一般情况下很少用到这 个参数);参数proxies用于设置代理(这里不详细讲怎么使用代理,感兴趣的看客可以去翻阅Python手册urllib模块)。urlopen返回 一个类文件对象,他提供了如下方法:

    read() , readline() , readlines() , fileno() , close() :这些方法的使用方式与文件对象完全一样;
    info():返回一个httplib.HTTPMessage 对象,表示远程服务器返回的头信息;
    getcode():返回Http状态码。如果是http请求,200表示请求成功完成;404表示网址未找到;
    geturl():返回请求的url;
下面来扩充一下上面的例子,看官可以运行一下这个例子,加深对urllib的印象:

google = urllib.urlopen('http://www.google.com')
print 'http header:/n', google.info()
print 'http status:', google.getcode()
print 'url:', google.geturl()
for line in google: # 就像在操作本地文件
    print line,
google.close()
urllib.urlretrieve(url[, filename[, reporthook[, data]]]):
urlretrieve方法直接将远程数据下载到本地。参数filename指定了保存到本地的路径(如果未指定该参数,urllib会生成一个临时文件 来保存数据);参数reporthook是一个回调函数,当连接上服务器、以及相应的数据块传输完毕的时候会触发该回调。我们可以利用这个回调函 数来显示当前的下载进度,下面的例子会展示。参数data指post到服务器的数据。该方法返回一个包含两个元素的元组(filename, headers),filename表示保存到本地的路径,header表示服务器的响应头。下面通过例子来演示一下这个方法的使用,这个例子将新浪首页
的html抓取到本地,保存在D:/sina.html文件中,同时显示下载的进度。

def cbk(a, b, c):
        '''''回调函数
        <a href="http://my.oschina.net/anchoret" class="referer" target="_blank">@a</a> : 已经下载的数据块
        @b: 数据块的大小
        <a href="http://my.oschina.net/congee" class="referer" target="_blank">@c</a> : 远程文件的大小
        '''
        per = 100.0 * a * b / c
        if per > 100:
            per = 100
        print '%.2f%%' % per
      url = 'http://www.sina.com.cn'
    local = 'd://sina.html'

    urllib.urlretrieve(url, local, cbk)
上面介绍的两个方法是urllib中最常用的方法,这些方法在获取远程数据的时候,内部会使用URLopener或者 FancyURLOpener类。作为urllib的使用者,我们很少会用到这两个类,这里我不想多讲。如果对urllib的实现感兴趣, 或者希望urllib支持更多的协议,可以研究这两个类。在Python手册中,urllib的作者还列出了这个模块的缺陷和不足,感兴趣的同学可以打开 Python手册了解一下。

    urllib中还提供了一些辅助方法,用于对url进行编码、解码。url中是不能出现一些特殊的符号的,有些符号有特殊的用途。我们知道以get方式提 交数据的时候,会在url中添加key=value这样的字符串,所以在value中是不允许有'=',因此要对其进行编码;与此同时服务器接收到这些参 数的时候,要进行解码,还原成原始的数据。这个时候,这些辅助方法会很有用:

urllib.quote(string[, safe]):对字符串进行编码。参数safe指定了不需要编码的字符;
urllib.unquote(string) :对字符串进行解码;
urllib.quote_plus(string [ , safe ] ) :与urllib.quote类似,但这个方法用'+'来替换' ',而quote用'%20'来代替' '
urllib.unquote_plus(string ) :对字符串进行解码;
urllib.urlencode(query[, doseq]):将dict或者包含两个元素的元组列表转换成url参数。例如 字典{'name': 'dark-bull', 'age': 200}将被转换为"name=dark-bull&age=200"
urllib.pathname2url(path):将本地路径转换成url路径;
urllib.url2pathname(path):将url路径转换成本地路径


data = 'name = ~a+3'
data1 = urllib.quote(data)
print data1 # result: name%20%3D%20%7Ea%2B3
print urllib.unquote(data1) # result: name = ~a+3
data2 = urllib.quote_plus(data)
print data2 # result: name+%3D+%7Ea%2B3
print urllib.unquote_plus(data2)    # result: name = ~a+3
data3 = urllib.urlencode({ 'name': 'dark-bull', 'age': 200 })
print data3 # result: age=200&name=dark-bull
data4 = urllib.pathname2url(r'd:/a/b/c/23.php')
print data4 # result: ///D|/a/b/c/23.php
print urllib.url2pathname(data4)    # result: D:/a/b/c/23.php

########################################

前阶段使用到ftp,写了个工具脚本http://blog.csdn.net/wklken/article/details/7059423

最近需要抓网页,看了下python抓取方式

 

需求:

抓取网页,解析获取内容

 

涉及库:【重点urllib2】

urllib   http://docs.python.org/library/urllib.html

urllib2  http://docs.python.org/library/urllib2.html

httplib   http://docs.python.org/library/httplib.html

 

 

使用urllib:

1.      抓取网页信息

 

urllib.urlopen(url[, data[, proxies]]) :

url: 表示远程数据的路径

data: 以post方式提交到url的数据

proxies:用于设置代理

 

urlopen返回对象提供方法:

-         read() , readline() ,readlines() , fileno() , close() :这些方法的使用方式与文件对象完全一样

-         info():返回一个httplib.HTTPMessage对象,表示远程服务器返回的头信息

-         getcode():返回Http状态码。如果是http请求,200请求成功完成;404网址未找到

-         geturl():返回请求的url

 

使用:

  1. #!/usr/bin/python 
  2. #
    -*- coding:utf-8 -*-
     
  3. #
    urllib_test.py
     
  4. #
    author:wklken
     
  5. #
    2012-03-17  wklken#yeah.net 
     
  6.  
  7. import os 

抱歉!评论已关闭.