精华内容
下载资源
问答
  • urllib为python内置的HTTP请求,包含四个模块:request:最基本的HTTP请求模块, 只需要传入URL参数error:异常处理模块parse:工具模块,处理URL,拆分、解析合并等robotparser:识别robots.txt文件1....

    urllib为python内置的HTTP请求库,包含四个模块:

    request:最基本的HTTP请求模块, 只需要传入URL和参数

    error:异常处理模块

    parse:工具模块,处理URL,拆分、解析合并等

    robotparser:识别robots.txt文件

    1. urlopen()

    实现最基本的请求发起,urlopen(url, data=None, [timeout,]*,cafile=None,capath=None,cadefault=False,context=None)

    代码:

    输出:

    response为HTTPRsponse对象:

    方法包含:read(),readinto(),getheader(name),getheaders(),fileno()

    属性包含:msg,version,status,reason,debuglevel、closed

    .data参数

    如果不加参数为GET请求,加参数则为POST请求,参数需要先转化为bytes类型

    代码:

    .timeout参数

    设置超时时间,单位为秒,如果请求在设置时间内没有响应,就会抛出异常,默认为全局时间

    .其他参数

    cafile和capath指定CA证书和路径,context必须是ssl.SSLContext类型,用来指定SSL设置

    2. Request

    urlopen()只能发起简单的请求,Request可以构建完整的请求信息,然后将Request对象传递给urlopen

    Request(url, data=None, headers={},origin_req_host=None, unverifiable=False,method=None)

    参数:

    url:必填,其余为选填

    data:同上

    headers:是一个字典,请求头,可以用req.add_headers()方法添加

    origin_req_host:请求方的主机名称或ip地址

    unverifiable:请求是否是无法验证的,默认False

    method:请求方法,GET,POST,PUT等

    代码:

    3.高级用法Handler

    处理更高级的操作,如Cookies,代理,登录验证等。Handler是urllib.request的类

    思路:用Handler类构建一个handler------通过build_opener()方法和handle构造一个opener------通过opener的open()方法发送请求

    案例---构造普通的handler

    踩坑:

    1.新建python文件时命名为urllib,导包报错---py文件名不能用库和关键字名称命名;

    展开全文
  • 分析信息本文主要介绍第一部分,如何用Python内置的库urllib和第三方requests来完成网页的获取。阅读完本文后,读者将能利用这2个获取一个网页的HTML代码。但是首先,我们需要一点网络方面的基本知识,才能更...

    引言:

    一个网络爬虫的编写主要可以分为三个部分:

    1.获取网页

    2.提取信息

    3.分析信息

    本文主要介绍第一部分,如何用Python内置的库urllib和第三方库requests库来完成网页的获取。阅读完本文后,读者将能利用这2个库获取一个网页的HTML代码。

    但是首先,我们需要一点网络方面的基本知识,才能更好的理解爬虫。

    为此,读者应该理解以下知识:

    1.什么是HTTP,HTTP报文及其格式

    2.请求报文的几种方法

    3.header(首部)常用字段

    4.HTTP如何保存会话信息,cookie和session

    本文第一部分网络基础会讨论这些问题

    一、网络基础

    1.什么是HTTP,HTTP报文及其格式

    超文本传输协议(HTTP,HyperText Transfer Protocol)位于OSI四层模型中的应用层协议。设计该协议的主要目的就是为了HTML的发送和接收。它基于TCP/IP协议。一次完整的HTTP事务包含以下过程:

    1)当我们在浏览器输入网址后,首先经过DNS服务器,解析域名,得到我们要获取的服务器IP,端口,已经资源的路径

    2)TCP三次握手,建立连接

    3)客户端发起HTTP请求报文

    4)服务器接受到客户端的请求报文,返回一个响应报文

    5)浏览器收到响应报文,解析HTML,CSS

    HTTP报文的三个组成部分(起始行,首部,主体)。

    起始行和首部是ASCII文本。每行用CRLF作为终止(回车ASCII13和换行ASCII10)主体是可选数据块,可包含文本或二进制数据,也可为空。

    报文主要分为请求报文和响应报文。

    请求报文格式

    响应报文格式

    一个获取gif图的例子:

    GET /specials/saw-blade.git HTTP/1.0

    Host: www.joes-hardware.com

    HTTP/1.0 200 OK

    Content-Type: image/git

    Content-Length: 8572

    method:客户端希望服务器对资源执行的动作。GET/HEAD/POST

    request-URL:命名了所请求的资源。

    version:格式看起来是这样的 HTTP/.

    status-code:三位数字描述了请求所发生的情况

    reason-phrase:原因短语,数字状态码的可读版本。只对人类有意义,还是以status-code为准

    header:可有0个或多个。每个首部包含:一个名字,冒号,一个可选的空格,值,最后是一个CRLF。一组HTTP首部应该总以一个空行(单个CRLF)结束。

    entity-body:由任意数据组成的数据块。如果不包含实体的主题部分,以一个CRLF结束

    2.请求报文的几种方法

    GET是HTTP的默认请求方式

    POST一般用来上传文件或表单

    HEAD获取某个URI响应头信息,基本与GET相同但是不返回响应主体。

    PUT通过提供的URI获取到特定的内容主体,如果存在则修改内容,如果不存在则创建。

    DELETE通过URI删除指定内容TRACE返回接受到的请求,用来查看数据经过中间服务器时发生了哪些变动

    OPTIONS返回给定URL支持的所有HTTP方法

    CONNECT要求使用SSL和TLS进行TCP通信

    PATCH请求修改局部数据

    Python爬虫对GET和POST方法使用的较多。

    3.header(首部)常用字段

    Accept

    Accept-Encoding

    Accept-Language

    Connection

    Host

    Cache-control

    User-Agent

    Upgrade-Insecure-Requests

    Cookies

    Referer

    Accept-Charset

    If-Modified-Since

    Pragma

    Range

    4.HTTP如何保存会话信息,cookie和session

    HTTP是一种无状态的协议。

    假设我们登陆一个网站,填完用户名和密码,然后点击提交按钮,浏览器发送了一个POST请求给服务器。服务器去查找数据库,比对用户名和密码成功后,返回一个响应报文,登陆成功,这一次HTTP事务结束。等用户再次发送一个请求,服务器也收到了这个请求,但是因为HTTP的无状态,服务器无法分辨这个报文是来自谁的。

    所以,为了能够让服务器知道这个请求的发送者和上次发送POST请求的发送者是同一个,我们需要标识用户的身份,来方便服务器辨认。

    对于服务器而言,我们需要有一个保存上下文的机制。session正是这样一种机制。对于每个用户产生的信息,服务器会以变量的方式保存下来,而每个用户都有一个ID,我们称为sessionID。

    但是仅有服务器的sessionID是没用的。就像你去图书馆借书,图书馆有你借书证的信息,但你没带借书证,就无法证明自己的身份信息。同样,客户端要证明自己的身份,就需要在请求报文中包含sessionID。对此,我们有以下几种方式。一种是URL重写,直接在URL中包含sessionID;一种是在表单中设置一个隐藏字段,将sessionID放在隐藏字段中提交表单,还有一种就是使用cookie。

    和session放在服务器相对,cookie作为一段数据储存在本地客户端。服务器在生成sessionID后,会再响应报文中包含set-cookie字段。客户端从中解析出cookie信息。之后在发请求报文时,将cookie加在报文里面发出去,服务器就能辨认这个请求报文的发送者是谁了。

    二、urllib库和requests库的使用

    1.urllib库

    urllib是Python3中的内置库,将Python2中的urllib和urllib2合二为一。

    urllib有四个重要属性:error,parser,request,response

    下面介绍一些比较常用的方法:

    urllib.request.urlopen

    def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TI

    MEOUT,*, cafile=None, capath=None,

    cadefault=False, context=None):

    pass

    data参数常用在POST请求,是一个byte object.我们可以先写成字典格式,然后用urllib.parse.urlencode()转换

    timeout是超时时间,单位是秒

    该函数返回一个类文件对象。该对象有如下常用方法:

    read:读出html

    geturl:返回url,常用来看是否重定向

    info:返回元信息,例如headers

    getcode:返回HTTP状态码

    urllib.request.Request

    class Request:

    def __init__(self, url, data=None, headers={},

    origin_req_host=None, unverifiable=False,

    method=None):

    headers用来写头部信息如user-agent,来伪装成浏览器发出的请求。

    一个例子:

    from urllib importrequest, error, parsetry:

    headers= {'Accept':'text/html, application/xhtml+xml, image/jxr, */*','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko','Accept-Language': 'zh-Hans-CN,zh-Hans;q=0.5'}

    value= {'source':'index_nav','form_email':'user', #这里是豆瓣用户名'form_password':'passwd'} #这里是密码

    data= parse.urlencode(value).encode('utf-8')

    req= request.Request('https://www.douban.com', headers=headers, data=data)

    res=request.urlopen(req)print(res.read().decode('utf-8'))excepterror.HTTPError as e:print('http error.')excepterror.URLError as e:print('url error')

    urllib.error.HTTPError和urllib.error.URLError

    from urllib importrequest, errortry:

    header= {'user-agent': r'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0'}

    req= request.Request('http://www.baidu.com', headers =header)

    res=request.urlopen(req)print(res.read().decode('utf-8'))excepterror.HTTPError as e:print('http error.')excepterror.URLError as e:print('url error.')

    urllib.request.proxyHandle

    设置代理ip信息。用以下代码替换urlopen

    #创建代理字典

    proxy={'http':'115.2.332.1:8081'}#使用ProxyHandler方法生成处理器对象

    proxy_handler=request.ProxyHandler(proxy)#创建代理IP的opener实例

    opener=request.build_opener(proxy_handler)

    html= opener.open(req)

    2.requests库

    requests库是第三方库,需要安装。如果你有pip工具,可以执行‘pip install requests’安装

    参考资料:

    《HTTP权威指南》

    展开全文
  • 刚刚接触爬虫,基础的东西得时时回顾才行,这么全面的帖子无论如何也得厚着脸皮转过来啊!...urllib 模块提供的上层接口,使访问 www ftp 上的数据就像访问本地文件一样。有以下几种模块:1.urllib.requ...

    刚刚接触爬虫,基础的东西得时时回顾才行,这么全面的帖子无论如何也得厚着脸皮转过来啊!

    原帖地址:https://www.2cto.com/kf/201801/714859.html

    什么是 Urllib 库?

    urllib 库 是 Python 内置的 HTTP 请求库。urllib 模块提供的上层接口,使访问 www 和 ftp 上的数据就像访问本地文件一样。

    有以下几种模块:

    1.urllib.request 请求模块

    2. urllib.error 异常处理模块

    3. urllib.parse url 解析模块

    4. urllib.robotparser robots.txt 解析模块

    Urllib 库下的几种模块基本使用如下:

    urllib.request

    关于 urllib.request: urllib.request 模块提供了最基本的构造 HTTP (或其他协议如 FTP)请求的方法,利用它可以模拟浏览器的一个请求发起过程。利用不同的协议去获取 URL 信息。它的某些接口能够处理基础认证 ( Basic Authenticaton) 、redirections (HTTP 重定向)、 Cookies (浏览器 Cookies)等情况。而这些接口是由 handlers 和 openers 对象提供的。

    一. urlopen

    1

    urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

    参数说明:

    url:需要打开的网址 data: Post 提交的数据, 默认为 None ,当 data 不为 None 时, urlopen() 提交方式为 Post timeout:设置网站访问超时时间

    下面是一个请求实例:

    1

    2

    3

    4

    5

    6

    import urllib.request

    # 可以是 from urllibimport request,语句等价

    response = urllib.request.urlopen()

    print("查看 response 响应信息类型: ",type(response))

    page = response.read()

    print(page.decode('utf-8'))

    输出情况:

    1

    2

    3

    查看 response 响应信息类型:

    说明: 直接使用 urllib.request 模块中的 urlopen方法获取页面,其中 page 数据类型为 bytes 类型,经过 decode 解码 转换成 string 类型。通过输出结果可以 urlopen 返回对象是 HTTPResposne 类型对象。

    urlopen 返回一个类文件对象,并提供了如下方法:

    read() , readline() , readlines() , fileno() , close() :这些方法的使用方式与文件对象完全一样; info():返回一个httplib.HTTPMessage对象,表示远程服务器返回的头信息;可以通过Quick Reference to Http Headers查看 Http Header 列表。 getcode():返回Http状态码。如果是http请求,200表示请求成功完成;404表示网址未找到; geturl():返回获取页面的真实 URL。在 urlopen(或 opener 对象)可能带一个重定向时,此方法很有帮助。获取的页面 URL 不一定跟真实请求的 URL 相同。

    使用实例:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    import urllib.request

    response = urllib.request.urlopen()

    print("查看 response 的返回类型:",type(response))

    print("查看反应地址信息: ",response)

    print("查看头部信息1(http header):\n",response.info())

    print("查看头部信息2(http header):\n",response.getheaders())

    print("输出头部属性信息:",response.getheader("Server"))

    print("查看响应状态信息1(http status):\n",response.status)

    print("查看响应状态信息2(http status):\n",response.getcode())

    print("查看响应 url 地址:\n",response.geturl())

    page = response.read()

    print("输出网页源码:",page.decode('utf-8'))

    显示输出:限于幅度,可以自行测试。

    关于 Post 数据

    下面是一个 Post 实例:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    import urllib.request,urllib.parse

    headers = {

    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36',

    'Connection':'keep-alive'

    }

    # 模拟表单提交

    dict = {

    'name':'MIka',

    'old:':18

    }

    data = urllib.parse.urlencode(dict).encode('utf-8')

    \#data 数如果要传bytes(字节流)类型的,如果是一个字典,先用urllib.parse.urlencode()编码。

    req = urllib.request.Request(url = url,data = data,headers = headers)

    response = urllib.request.urlopen(req)

    page = response.read().decode('utf-8')

    print(page)

    注解:

    如实例易知,在 urlopen 参数 data 不为 None 时,urlopen() 数据提交方式 为 Post。urllib.parse.urlencode()方法将参数字典转化为字符串。

    提交的网址是httpbin.org,它可以提供HTTP请求测试。 https://httpbin.org/post 这个地址可以用来测试 POST 请求,它可以输出请求和响应信息,其中就包含我们传递的 data 参数。

    关于 timeout 参数

    timeout参数可以设置超时时间,单位为秒,意思就是如果请求超出了设置的这个时间还没有得到响应,就会抛出异常,如果不指定,就会使用全局默认时间。它支持 HTTP 、 HTTPS 、 FTP 请求。

    相关实例:

    1

    2

    3

    import urllib.request

    response = urllib.request.urlopen(,timeout=1)

    print(response.read().decode("utf-8"))

    输出结果:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    "args": {},

    "headers": {

    "Accept-Encoding":"identity",

    "Connection":"close",

    "Host":"httpbin.org",

    "User-Agent":"Python-urllib/3.6"

    },

    "origin":"119.137.62.237",

    }

    我们试着给timeout一个更小的值,例如timeout=0.1,此时抛出 urllib.error.URLError 异常,错误原因为 time out 。因为常理下 0.1 s 内根本就不可能得到服务器响应。所以通过设置参数 timeout 的值对于应对网页响应的速度具有一定的意义。同时,可以通过设置这个超长时间来控制一个网页如果长时间未响应就跳过它的抓取(可以通过try-catch 语句)。

    try-catch 实现异常处理:

    1

    2

    3

    4

    5

    6

    7

    8

    import urllib.request

    import socket

    import urllib.error

    try:

    response = urllib.request.urlopen(,timeout=0.1)

    except urllib.error.URLError as e:

    if isinstance(e.reason, socket.timeout):

    print("Time out!")

    输出:

    1

    Time out!

    关于其他参数

    Context 参数,必须是 ssl.SSL.Context 类型,用来指定 SSL 设置。cafile、capath 两个参数是指定 CA 证书和它的路径,在请求 HTTPS 连接时可能用的上。

    cadefault 参数已经弃用,默认为 False。

    二. Request

    1

    urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)

    使用request()来包装请求,再通过urlopen()获取页面。单纯使用 urlopen 并不能足以构建一个完整的请求,例如 对拉勾网的请求如果不加上 headers 等信息,就无法正常解析访问网页内容。

    下面是一个使用实例

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    import urllib.request

    headers = {

    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36',

    'Connection':'keep-alive'

    }

    req = request.Request(url, headers=headers)

    page = request.urlopen(req).read()

    page = page.decode('utf-8')

    print(page)

    headers 的参数设置:

    User-Agent :这个头部可以携带如下几条信息:浏览器名和版本号、操作系统名和版本号、默认语言。这个数据可以从 网页开发工具上的请求反应信息中获取(浏览器上一般按 F12 打开开发工具)。作用是用于伪装浏览器。

    Referer:可以用来防止盗链,有一些网站图片显示来源 https://*.com ,就是检查 Referer 来鉴定的。

    Connection:表示连接状态,记录 Session 的状态。

    origin_req_host:请求方的 host 名称或者 IP 地址。

    unverifiable:指请求无法验证,默认为 False。用户并没有足够的权限来选择接收这个请求结果,例如请求一个 HTML 文档中的图片,但没有自动抓取图像的权限,这时 unverifiable 为 True。

    method:指定请求使用的方法,例如 GET、POST、PUT 等。

    三. Openers 和 Handlers

    当需要获取一个 URL 时需要使用一个 opener (这是一个不容易理解的对象—-urllib.request.OpenerDirector的实例)。一般情况下通过 urlopen 使用默认的 opener ,但允许自己创建不同的 opener 。Opener 会使用 handlers 。handler 承担”重活”并知道如何以某个特定的协议(如http,ftp等)打开 URL、知道如何处理 URL的某些行为(比如 Http 重定向或是 Cookie等)。

    引入 Opener(即 OpenerDirector 类)的目的是为了能够实现更高级的功能,一般情况下使用的 Request 、 urlopen() 相当于类库封装好了的极其常用的请求方法,利用这两个就可以完成基本的请求。但当需要实现更高级的功能时就需要更高级的实例来完成操作。所以,这里就用到了比调用 urlopen() 的对象的更普遍的对象—-Opener 。

    Opener 通过 Handler 构建,可以使用 open() 方法,返回的类型和 urlopen() 相同。

    OpenerDirector操作类是一个管理很多处理类(Handler)的类。这些 Handler 类都对应处理相应的协议,或者特殊功能。

    分别有下面的处理类(即 Handler 类):

    BaseHandler、HTTPErrorProcessor、HTTPDefaultErrorHandler、HTTPRedirectHandler、ProxyHandler、AbstractBasicAuthHandler、HTTPBasicAuthHandler、ProxyBasicAuthHandler、AbstractDigestAuthHandler、

    ProxyDigestAuthHandler、AbstractHTTPHandler、HTTPHandler、HTTPCookieProcessor、UnknownHandler、

    FileHandler、FTPHandler、CacheFTPHandler

    其中,urllib.request.BaseHandler 是所有其他 Handler 的父类,其提供了最基本的Handler方法。例如:default_open()、protocol_request() 等。

    常见的 BaseHandler 子类有:

    * HTTPDefaultErrorHandler :用于处理HTTP响应错误,错误都会抛出 HTTPError 类型的异常。

    * HTTPRedirectHandler :用于处理重定向。

    * HTTPCookieProcessor: 用于处理 Cookie 。

    * ProxyHandler :用于设置代理,默认代理为空

    * HTTPPasswordMgr : 用于管理密码,它维护了用户名密码的表。

    * HTTPBasicAuthHandler : 用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题。 另外还

    有其他的 Handler ,可以参考官方文档。

    基本认证(Basic Authentication)

    什么是基本认证?当访问网页信息时被要求需要认证(或授权)时,服务器会发送一个头信息(如果验证失败便返回 401 错误代码)请求认证。它指定了一个realm(领域)。这个头信息的形式看起来会像是:www-Authenticate:SCHEME realm="REALM",例如WWW-Authenticate: Basic realm="cPanel Users"

    接着,客户端应该使用正确的用户名和密码重新请求(请求头中应该包含对应的realm、用户名以及用户密码),这就是“基础认证”。

    通过创建一个 HTTPBasicAuthHandler 并利用 opener 使用这个 handler 可以简化这个认证过程。

    HTTPBasicAuthHandler使用一个叫做密码管理器(password manager)的对象处理 url 和 realm、用户名和密码之间的映射。如果你知道realm(领域)是什么(根据服务器发送的认证 headers 可以得知),那么你便可以使用 HTTPPasswordMgr。人们往往不在乎realm是什么。这种情况下,最方便的是使用HTTPPasswordMgrWithDefaultRealm。它允许你为一个url指定一个默认的用户名和密码。它会在你没有给某个realm提供用户名和密码的时候起作用。这种情况下,需要将 add_password 方法的 realm 参数设置为 None。

    顶层 URL (top-level URL)就是第一个需要认证的 URL,只有是比你传递给.add_password() 的 URL更“深层”的 URL 也可以匹配得上。

    下面是一个实例:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    # -*- coding: utf-8 -*-

    import urllib

    # 创建一个密码管理者

    password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()

    # 添加用户名和密码

    # 如果知道 realm, 我们可以使用他代替 ``None``.

    # password_mgr.add_password(None, top_level_url, username, password)

    password_mgr.add_password(None, top_level_url,'username','password')

    # 创建了一个新的handler

    handler = urllib.request.HTTPBasicAuthHandler(password_mgr)

    # 创建"opener" (OpenerDirector 实例)

    opener = urllib.request.build_opener(handler)

    # 使用 opener 获取一个URL

    x = opener.open(a_url)

    print(x.read().decode("utf-8"))

    # 安装 opener.

    # 现在所有调用 urllib.request.urlopen 将用我们的 opener.

    urllib.request.install_opener(opener)

    此处代码为实例代码,用于说明Handler和Opener的使用方法。在这里,首先实例化了一个HTTPPasswordMgrWithDefaultRealm 对象,然后利用 add_password() 添加进用户名和密码,相当于建立了一个处理认证的处理器。接下来利用 urllib.request.build_opener() 方法来利用这个处理器构建一个 Opener ,那么这个 Opener 在发送请求的时候就具备了认证功能了。最后通过 Opener 的 open() 方法打开 URL,即可以完成认证。

    说明几点:

    1.上面实例中,只将HTTPBasicAuthHandler提供给 build_opener 。

    2.默认情况下,opener可以处理一般情况的 handler—-ProxyHandler(已经设置了代理环境变量如 http_proxy)、UnknownHandler、HTTPHandler、HTTPDefaultErrorHandler、HTTPRedirectHandler、FTPHandler、FileHandler、DataHandler、HTTPErrorProcessor。

    实际上,toplevel_url 要么是一个完整的 URL(包括“http:”模式部分以及主机名和可选的端口号)比如“https://example.com/”,要么是一个“authority”(即主机名和可选的端口号)例如“example.com”或“example.com:8080”(后者包含了端口号)。该“authority”如果出现的话,不能包含“用户信息(userinfo)“元素——如“joe@password:example.com” 是不被允许的。

    代理

    urllib 可以通过 ProxyHandler 自动检测你的代理设置并使用它们。当代理设置被检测时,它是普通 handler 的一部分。通常认为这是好事,当有些情况它也可能没有用。一个不用定义代理设置并使用它们的是创建自己的 ProxyHandler。这个实现方法类似于创建一个基本认证 handler。

    下面是一个实例:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    #! /usr/bin/env python3

    import urllib.request

    proxy_handler = urllib.request.ProxyHandler({

    'socks5':'localhost:1080',

    })

    opener = urllib.request.build_opener(proxy_handler)

    response = opener.open()

    print(response.read())

    在这里使用了 ProxyHandler ,ProxyHandler 函数接受一个字典类型的参数,其中key为协议名称,比如 http 还是 https 等,value为代理链接(包含 host 名称与端口号),也支持带验证的代理,可以添加多个代理。然后利用 build_opener() 方法利用这个 Handler 构造一个 Opener ,然后发送请求即可。

    Cookie设置

    获取百度 Cookie 实例如下:

    1

    2

    3

    4

    5

    6

    7

    8

    #! /usr/bin/env python3

    import http.cookiejar, urllib.request

    cookie = http.cookiejar.CookieJar()

    handler = urllib.request.HTTPCookieProcessor(cookie)

    opener = urllib.request.build_opener(handler)

    response = opener.open()

    for item in cookie:

    print(item.name+"="+item.value)

    输出:

    1

    2

    3

    4

    5

    6

    BAIDUID=37998CB10856532A8604B84ACFCAB6C0:FG=1

    BIDUPSID=37998CB10856532A8604B84ACFCAB6C0

    H_PS_PSSID=25576_1466_13289_21122_20928

    PSTM=1516720556

    BDSVRTM=0

    BD_HOME=0

    首先声明一个CookieJar对象,接下来利用HTTPCookieProcessor构建一个 handler ,最后利用 build_opener 方法构建出 opener ,执行 open() 即可。

    查看输出可以发现每一条 Cookie 有相应的名称和值。

    文本存储 Cookie 信息实例如下:

    1

    2

    3

    4

    5

    6

    filename ='cookie.txt'

    cookie = http.cookiejar.MozillaCookieJar(filename)

    handler = urllib.request.HTTPCookieProcessor(cookie)

    opener = urllib.request.build_opener(handler)

    response = opener.open()

    cookie.save(ignore_discard=True, ignore_expires=True)

    cookie.txt 文件内容为:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    # Netscape HTTP Cookie File

    # https://curl.haxx.se/rfc/cookie_spec.html

    # This is a generated file! Do not edit.

    .baidu.com TRUE / FALSE3664204558 BAIDUID 43896422C89528C1D912D69D7AA9CF49:FG=1

    .baidu.com TRUE / FALSE3664204558 BIDUPSID 43896422C89528C1D912D69D7AA9CF49

    .baidu.com TRUE / FALSE H_PS_PSSID 1458_21084_17001_20718

    .baidu.com TRUE / FALSE3664204558 PSTM1516720911

    www.baidu.com FALSE / FALSE BDSVRTM0

    www.baidu.com FALSE / FALSE BD_HOME0

    相对单纯输出 Cookie ,这里 CookieJar 换成 MozillaCookieJar(CookieJar 的子类) ,用于生成文件。MozillaCookieJar可以用来处理 Cookie 以及和文件相关的事件,比如读取和保存 Cookie ,同时它可以将 Cookie 保存成 Mozilla 型的格式。

    此外,还有一个LWPCookieJar,同样可以读取和保存 Cookie ,但是保存的格式和 MozillaCookieJar 的不一样,它会保存成 libwww-perl 的 Set-Cookie3 文件格式的 Cookie 。

    尝试一下,修改声明 cookie = http.cookiejar.LWPCookieJar(filename)

    新cookie.txt 文件内容为:

    1

    2

    3

    4

    5

    6

    7

    #LWP-Cookies-2.0

    Set-Cookie3: BAIDUID="CDA35482887BF4DEAA078F12CD69DDD8:FG=1"; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2086-02-10 18:47:45Z"; version=0

    Set-Cookie3: BIDUPSID=CDA35482887BF4DEAA078F12CD69DDD8; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2086-02-10 18:47:45Z"; version=0

    Set-Cookie3: H_PS_PSSID=25641_1424_21108_17001; path="/"; domain=".baidu.com"; path_spec; domain_dot; discard; version=0

    Set-Cookie3: PSTM=1516721618; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2086-02-10 18:47:45Z"; version=0

    Set-Cookie3: BDSVRTM=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0

    Set-Cookie3: BD_HOME=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0

    以下为以 LWPCookieJar 格式为例实现对 Cookie 文件的读取与利用:

    1

    2

    3

    4

    5

    6

    cookie = http.cookiejar.LWPCookieJar()

    cookie.load('cookie.txt', ignore_discard=True, ignore_expires=True)

    handler = urllib.request.HTTPCookieProcessor(cookie)

    opener = urllib.request.build_opener(handler)

    response = opener.open()

    print(response.read().decode('utf-8'))

    前提是先利用上面的方式生成了 LWPCookieJar 格式的 Cookie 文件 ,然后利用 load() 方法,传入文件名称,构建 handler 和 opener 并能够正常输出百度网页的源代码。

    以上是关于 urllib.request 模块的常用知识以及重点内容的总结, 还具体说明了 urllib.request,urlopen() 的详细介绍以及用法。可以查看 python doc 。

    下面是 urllib.request 模块的其他 方法或者类的简要介绍:

    方法:

    1. install_opener()

    urllib.request.install_opener(opener)

    安装一个 OpenerDirector实例作为全球默认的opener 。如果你想让 urlopen 使用这个opener,那么安装一个opener是必要的;否则可以简单地调用OpenerDirector.open()而不是urlopen()。这样代码不会检查一个真实的 OpenerDirector 并且任何类的适当的接口都可以运作。

    2.build_opener()

    urllib.request.build_opener([handler, …])

    返回一个顺序链的处理程序OpenerDirector的实例。处理程序可以是BaseHandler的实例,或者 BaseHandler 的子类(在这种情况下,必须调用没有参数的构造函数)。下面这些类的实例将提前处理程序,除非处理程序包含它们,或者它们子类的实例:ProxyHandler(如果检测到代理设置)、UnknownHandler、HTTPHandler、HTTPDefaultErrorHandler、HTTPRedirectHandler、FTPHandler、FileHandler、HTTPErrorProcessor。

    如果 Python 安装 SSL 支持(即如果 ssl 模块可以被导入), HTTPSHandler 也将被添加。

    一个 BaseHandler 子类也可以通过改变它的 handler_order 属性来修改它再处理程序列表中的位置。

    3.pathname2url()

    urllib.request.pathname2url(path)

    将路径名转换成路径,从本地语法形式的路径中使用一个URL的路径组成部分。这不会产生一个完整的URL。它将返回引用 quote() 函数的值。

    4.url2pathname()

    urllib.request.url2pathname(path)

    将路径组件转换为本地路径的语法。这个不接受一个完整的URL。这个函数使用 unquote() 解码的通路。

    5.getproxies()

    urllib.request.getproxies()

    这个 helper 函数返回一个日程表 dictionary 去代理服务器的 URL 映射。扫描指定的环境变量 _proxy 大小写不敏感的方法,对所有的操作系统,当它不能找到它,从 Mac OS X 的 Mac OSX 系统配置和 Windows 系统注册表中寻找代理信息。如果两个大写和小写环境变量存在(或不一样),小写优先。

    请注意,如果环境变量 REQUEST_METHOD 已被设置,这通常表明你在 CGI 脚本运行环境,此时环境变量 HTTP_PROXY(大写 _PROXY) 将被忽略。这是因为该变量可以被客户端使用注射 “代理:” HTTP 头。如果你需要使用一个 HTTP 代理在 CGI 环境中,要么使用 ProxyHandler 明确,或者确保变量名小写(或至少是 _proxy后缀)。

    类:

    urllib.request.Request(url,data=None,headers={}, origin_req_host=None, unverifiable=False, method=None)

    1.这个类是一个抽象的 URL 请求。

    2.url 应该是一个字符串包含一个有效的 URL 。

    3.数据必须是一个字节对象指定额外的数据发送到服务器 或 None。如果没有这样的数据是必要的,数据也可能是一个 iterable 对象而且在这种情况下必须在最开始时指定内容的长度。目前 HTTP 是唯一一个这样请求数据的,当数据参数被提供时,HTTP 请求将会执行 POST 请求而不是 GET 请求。

    4.数据应该是一个缓冲的在标准应用程序中以x-www-form-urlencoded的格式。 urllib.parse.urlencode() 函数接受一个映射或序列集合,并返回一个 ASCII 文本字符串的格式。它应该在被用作数据参数之前,被编码为字节。

    5.headers 应该是一个字典,如果 add_header() 被称为与每个键和值作为参数。这通常是用来“恶搞” User-Agent 头的值,因为使用一个浏览器识别本身——一些常见HTTP服务器只允许请求来自浏览器而不是脚本。例如,Mozilla Firefox可能识别本身 “Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11”。而 urllib 默认的用户代理字符串 是”Python-urllib/2.6”在Python 2.6()。

    6.一个Content-Type header的例子: 用数据论证将发送一个字典 {“Content-Type”:”application/x-www-form-urlencoded”}。

    7.最后两个参数只是正确处理第三方 HTTP cookie:

    origin_req_host应该请求原始的主机交易,就像定义的 RFC 2965。它默认为 http.cookiejar.request_host(self)。这是原始请求的主机名或 IP 地址,由用户发起。例如。如果请求是一个图像在 HTML文档中,这应该是请求的请求主机包含图像的页面。

    8.无法核实的表明是否应该请求是无法核实的,这由 RFC 2965 定义。它默认为 False。一个无法核实的请求的 URL 的用户没有允许的选择。例如,如果请求是一个图像在一个HTML文档,和用户没有选择通过图像的自动抓取,这应该是正确的。

    9.这个方法应该是一个字符串,表示将使用(如 headers 请求头部信息)。如果提供,其值是存储在 method 属性和使用 get_method()。通过设置子类可能表明一个默认的方法 method类 本身的属性。

    urllib.request.OpenerDirector

    OpenerDirector 类打开 url 并通过 BaseHandler 连接在一起。它管理处理程序的连接,和恢复错误。

    urllib.request.BaseHandler

    这是对于所有已注册的处理程序的基类。

    urllib.request.HTTPRedirectHandler

    一个类来处理重定向。

    urllib.request.HTTPCookieProcessor(cookiejar=None)

    一个类来处理HTTP cookie。

    urllib.request.ProxyHandler(proxies=None)

    导致请求通过一个代理。如果代理是给定的,它必须是一个字典的代理协议名称映射到 ur l。默认值是从环境变量的列表 _proxy 中读取代理。如果没有代理设置环境变量,那么在 Windows 环境中代理设置了从注册表部分的网络设置,在 Mac OS X 环境代理信息检索的 OS X 系统配置框架。

    禁用一个代理传递一个空的字典。

    no_proxy 环境变量可以被用来指定主机不能通过代理;如果设置,它应该是一个以逗号分隔的主机名后缀。可选 :port 附加为例 cern.ch,ncsa.uiuc.edu,some.host:8080。

    请注意:HTTP_PROXY 如果一个变量将被忽略 REQUEST_METHOD 设置;参见文档 getproxies()。

    urllib.request.HTTPPasswordMgr

    保持一个(realm, uri) -> (user, password) 映射的数据库 。

    urllib.request.HTTPPasswordMgrWithDefaultRealm

    保持一个 (realm, uri) -> (user, password) 映射的数据库 。如果没有其他搜索领域,一个值为 None 的领域 (realm) 被认为是一个全方位领域。

    urllib.request.HTTPPasswordMgrWithPriorAuth

    保持一个 HTTPPasswordMgrWithDefaultRealm 变量 还有一个uri -> is_authenticated 映射的数据库 。当发送身份认证可以马上使用 BasicAuth handler 确认身份, 而不是等待 401 报错响应。

    urllib.request.AbstractBasicAuthHandler(password_mgr=None)

    这是 mixin 类,处理远程主机身份认证和代理。使用 is_authenticated 值对于一个给定的URI 来决定是否发送请求来进行身份认证。如果 s_authenticated 返回 True 则发送凭证。如果 is_authenticated 是 False ,则凭证不发送。如果 返回 401 错误响应信息,则身份认证失败。如果身份验证成功, update_authenticated 被称为设置 True。

    urllib.request.HTTPBasicAuthHandler(password_mgr=None)

    处理远程主机的身份认证。

    urllib.request.ProxyBasicAuthHandler(password_mgr=None)

    处理身份认证与代理。

    urllib.request.AbstractDigestAuthHandler(password_mgr=None)

    这是 mixin 类,处理远程主机身份认证和代理。

    urllib.request.HTTPDigestAuthHandler(password_mgr=None)

    实现远程主机的身份认证。如果有password_mgr,应该是兼容HTTPPasswordMgr的;请参阅章节 HTTPPasswordMgr以获取很多接口信息。Digest认证处理器和基本认证处理器都被加入,Digest认证处理器总是首先进行验证。如果主机再次返回一个40X 响应,它发送到基本认证处理器进行处理。当出现除了 Digest 或基本身份的其他身份认证时,这个处理程序方法将提高 ValueError 3.3版本的变化:提高 ValueError不支持的身份验证方案。

    urllib.request.ProxyDigestAuthHandler(password_mgr=None)

    处理代理身份的验证。如果有password_mgr,应该是兼容HTTPPasswordMgr的;请参阅章节HTTPPasswordMgr 获取更多接口信息。

    urllib.request.HTTPHandler

    处理HTTP URLs。

    urllib.request.HTTPSHandler(debuglevel=0, context=None, check_hostname=None)

    处理开放的 HTTPS URLs 。在 http.client.HTTPSConnection 中 context 和 check_hostname 有相同的意义 。

    urllib.request.FileHandler

    打开本地文件。

    urllib.request.DataHandler

    开放数据 URLs。

    urllib.request.FTPHandler

    开放的 FTP URLs。

    urllib.request.CacheFTPHandler

    打开 FTP URLS,保持打开的 FTP 连接缓存来减少延迟。

    urllib.request.UnknownHandler

    全方位类处理未知的 URLs。

    urllib.request.HTTPErrorProcessor

    HTTP 错误响应过程。

    想了解更多Python关于爬虫、数据分析的内容,欢迎大家关注我的微信公众号:悟道Python

    1252647-20190310201040012-1816135231.png

    展开全文
  • 刚刚接触爬虫,基础的东西得时时回顾才行,这么全面的帖子无论如何也得厚着脸皮转过来啊!...urllib 模块提供的上层接口,使访问 www ftp 上的数据就像访问本地文件一样。 有以下几种模块:...

    刚刚接触爬虫,基础的东西得时时回顾才行,这么全面的帖子无论如何也得厚着脸皮转过来啊!

    原帖地址:https://www.2cto.com/kf/201801/714859.html

    什么是 Urllib 库?

    urllib 库 是 Python 内置的 HTTP 请求库。urllib 模块提供的上层接口,使访问 www 和 ftp 上的数据就像访问本地文件一样。

    有以下几种模块:

    1.urllib.request 请求模块

    2. urllib.error 异常处理模块

    3. urllib.parse url 解析模块

    4. urllib.robotparser robots.txt 解析模块

    Urllib 库下的几种模块基本使用如下:

    urllib.request

    关于 urllib.request: urllib.request 模块提供了最基本的构造 HTTP (或其他协议如 FTP)请求的方法,利用它可以模拟浏览器的一个请求发起过程。利用不同的协议去获取 URL 信息。它的某些接口能够处理基础认证 ( Basic Authenticaton) 、redirections (HTTP 重定向)、 Cookies (浏览器 Cookies)等情况。而这些接口是由 handlers 和 openers 对象提供的。

    一. urlopen
    1
    urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

    参数说明

    url:需要打开的网址 data: Post 提交的数据, 默认为 None ,当 data 不为 None 时, urlopen() 提交方式为 Post timeout:设置网站访问超时时间

    下面是一个请求实例:

    1
    2
    3
    4
    5
    6
    import urllib.request
    # 可以是 from urllib import request,语句等价
    response = urllib.request.urlopen('https://www.baidu.com')
    print("查看 response 响应信息类型: ",type(response))
    page = response.read()
    print(page.decode('utf-8'))

    输出情况:

    1
    2
    3
    查看 response 响应信息类型:  <class>
     
    <!--STATUS OK--></class>

    说明: 直接使用 urllib.request 模块中的 urlopen方法获取页面,其中 page 数据类型为 bytes 类型,经过 decode 解码 转换成 string 类型。通过输出结果可以 urlopen 返回对象是 HTTPResposne 类型对象。

    urlopen 返回一个类文件对象,并提供了如下方法:

    read() , readline() , readlines() , fileno() , close() :这些方法的使用方式与文件对象完全一样; info():返回一个httplib.HTTPMessage对象,表示远程服务器返回的头信息;可以通过Quick Reference to Http Headers查看 Http Header 列表。 getcode():返回Http状态码。如果是http请求,200表示请求成功完成;404表示网址未找到; geturl():返回获取页面的真实 URL。在 urlopen(或 opener 对象)可能带一个重定向时,此方法很有帮助。获取的页面 URL 不一定跟真实请求的 URL 相同。

    使用实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import urllib.request
    response = urllib.request.urlopen('https://python.org/')
    print("查看 response 的返回类型:",type(response))
    print("查看反应地址信息: ",response)
    print("查看头部信息1(http header):\n",response.info())
    print("查看头部信息2(http header):\n",response.getheaders())
    print("输出头部属性信息:",response.getheader("Server"))
    print("查看响应状态信息1(http status):\n",response.status)
    print("查看响应状态信息2(http status):\n",response.getcode())
    print("查看响应 url 地址:\n",response.geturl())
    page = response.read()
    print("输出网页源码:",page.decode('utf-8'))

    显示输出:限于幅度,可以自行测试。

    关于 Post 数据

    下面是一个 Post 实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import urllib.request,urllib.parse
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36',
        'Referer': 'https://httpbin.org/post',
        'Connection': 'keep-alive'
        }
      # 模拟表单提交
    dict = {
        'name':'MIka',
        'old:':18
    }
    data = urllib.parse.urlencode(dict).encode('utf-8')
    \#data 数如果要传bytes(字节流)类型的,如果是一个字典,先用urllib.parse.urlencode()编码。
    req = urllib.request.Request(url = url,data = data,headers = headers)
    response = urllib.request.urlopen(req)
    page = response.read().decode('utf-8')
    print(page)

    注解
    如实例易知,在 urlopen 参数 data 不为 None 时,urlopen() 数据提交方式 为 Post。urllib.parse.urlencode()方法将参数字典转化为字符串。
    提交的网址是httpbin.org,它可以提供HTTP请求测试。 https://httpbin.org/post 这个地址可以用来测试 POST 请求,它可以输出请求和响应信息,其中就包含我们传递的 data 参数。

    关于 timeout 参数
    timeout参数可以设置超时时间,单位为秒,意思就是如果请求超出了设置的这个时间还没有得到响应,就会抛出异常,如果不指定,就会使用全局默认时间。它支持 HTTP 、 HTTPS 、 FTP 请求。

    相关实例

    1
    2
    3
    import urllib.request
    response = urllib.request.urlopen("https://httpbin.org/get",timeout=1)
    print(response.read().decode("utf-8"))

    输出结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      "args": {},
      "headers": {
        "Accept-Encoding": "identity",
        "Connection": "close",
        "Host": "httpbin.org",
        "User-Agent": "Python-urllib/3.6"
      },
      "origin": "119.137.62.237",
    }

    我们试着给timeout一个更小的值,例如timeout=0.1,此时抛出 urllib.error.URLError 异常,错误原因为 time out 。因为常理下 0.1 s 内根本就不可能得到服务器响应。所以通过设置参数 timeout 的值对于应对网页响应的速度具有一定的意义。同时,可以通过设置这个超长时间来控制一个网页如果长时间未响应就跳过它的抓取(可以通过try-catch 语句)。

    try-catch 实现异常处理

    1
    2
    3
    4
    5
    6
    7
    8
    import urllib.request
    import  socket
    import urllib.error
    try:
        response = urllib.request.urlopen('https://httpbin.org/get',timeout=0.1)
    except urllib.error.URLError as e:
        if  isinstance(e.reason, socket.timeout):
                print("Time out!")

    输出

    1
    Time out!

    关于其他参数

    Context 参数,必须是 ssl.SSL.Context 类型,用来指定 SSL 设置。cafile、capath 两个参数是指定 CA 证书和它的路径,在请求 HTTPS 连接时可能用的上。
    cadefault 参数已经弃用,默认为 False。

    二. Request
    1
    urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)

    使用request()来包装请求,再通过urlopen()获取页面。单纯使用 urlopen 并不能足以构建一个完整的请求,例如 对拉勾网的请求如果不加上 headers 等信息,就无法正常解析访问网页内容。

    下面是一个使用实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import urllib.request
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36',
        'Connection': 'keep-alive'
    }
    req = request.Request(url, headers=headers)
    page = request.urlopen(req).read()
    page = page.decode('utf-8')
    print(page)

    headers 的参数设置:

    User-Agent :这个头部可以携带如下几条信息:浏览器名和版本号、操作系统名和版本号、默认语言。这个数据可以从 网页开发工具上的请求反应信息中获取(浏览器上一般按 F12 打开开发工具)。作用是用于伪装浏览器。

    Referer:可以用来防止盗链,有一些网站图片显示来源 https://*.com ,就是检查 Referer 来鉴定的。

    Connection:表示连接状态,记录 Session 的状态。

    origin_req_host:请求方的 host 名称或者 IP 地址。

    unverifiable:指请求无法验证,默认为 False。用户并没有足够的权限来选择接收这个请求结果,例如请求一个 HTML 文档中的图片,但没有自动抓取图像的权限,这时 unverifiable 为 True。

    method:指定请求使用的方法,例如 GET、POST、PUT 等。

    三. Openers 和 Handlers

    当需要获取一个 URL 时需要使用一个 opener (这是一个不容易理解的对象—-urllib.request.OpenerDirector的实例)。一般情况下通过 urlopen 使用默认的 opener ,但允许自己创建不同的 opener 。Opener 会使用 handlers 。handler 承担”重活”并知道如何以某个特定的协议(如http,ftp等)打开 URL、知道如何处理 URL的某些行为(比如 Http 重定向或是 Cookie等)。

    引入 Opener(即 OpenerDirector 类)的目的是为了能够实现更高级的功能,一般情况下使用的 Request 、 urlopen() 相当于类库封装好了的极其常用的请求方法,利用这两个就可以完成基本的请求。但当需要实现更高级的功能时就需要更高级的实例来完成操作。所以,这里就用到了比调用 urlopen() 的对象的更普遍的对象—-Opener 。

    Opener 通过 Handler 构建,可以使用 open() 方法,返回的类型和 urlopen() 相同。

    OpenerDirector操作类是一个管理很多处理类(Handler)的类。这些 Handler 类都对应处理相应的协议,或者特殊功能。

    分别有下面的处理类(即 Handler 类):
    BaseHandler、HTTPErrorProcessor、HTTPDefaultErrorHandler、HTTPRedirectHandler、ProxyHandler、AbstractBasicAuthHandler、HTTPBasicAuthHandler、ProxyBasicAuthHandler、AbstractDigestAuthHandler、
    ProxyDigestAuthHandler、AbstractHTTPHandler、HTTPHandler、HTTPCookieProcessor、UnknownHandler、
    FileHandler、FTPHandler、CacheFTPHandler

    其中,urllib.request.BaseHandler 是所有其他 Handler 的父类,其提供了最基本的Handler方法。例如:default_open()、protocol_request() 等。

    常见的 BaseHandler 子类有:
    * HTTPDefaultErrorHandler :用于处理HTTP响应错误,错误都会抛出 HTTPError 类型的异常。
    * HTTPRedirectHandler :用于处理重定向。
    * HTTPCookieProcessor: 用于处理 Cookie 。
    * ProxyHandler :用于设置代理,默认代理为空
    * HTTPPasswordMgr : 用于管理密码,它维护了用户名密码的表。
    * HTTPBasicAuthHandler : 用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题。 另外还

    有其他的 Handler ,可以参考官方文档。

    基本认证(Basic Authentication)

    什么是基本认证?当访问网页信息时被要求需要认证(或授权)时,服务器会发送一个头信息(如果验证失败便返回 401 错误代码)请求认证。它指定了一个realm(领域)。这个头信息的形式看起来会像是:www-Authenticate:SCHEME realm="REALM",例如WWW-Authenticate: Basic realm="cPanel Users"

    接着,客户端应该使用正确的用户名和密码重新请求(请求头中应该包含对应的realm、用户名以及用户密码),这就是“基础认证”。

    通过创建一个 HTTPBasicAuthHandler 并利用 opener 使用这个 handler 可以简化这个认证过程。

    HTTPBasicAuthHandler使用一个叫做密码管理器(password manager)的对象处理 url 和 realm、用户名和密码之间的映射。如果你知道realm(领域)是什么(根据服务器发送的认证 headers 可以得知),那么你便可以使用 HTTPPasswordMgr。人们往往不在乎realm是什么。这种情况下,最方便的是使用HTTPPasswordMgrWithDefaultRealm。它允许你为一个url指定一个默认的用户名和密码。它会在你没有给某个realm提供用户名和密码的时候起作用。这种情况下,需要将 add_password 方法的 realm 参数设置为 None。

    顶层 URL (top-level URL)就是第一个需要认证的 URL,只有是比你传递给.add_password() 的 URL更“深层”的 URL 也可以匹配得上。

    下面是一个实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    # -*- coding: utf-8 -*- 
    import urllib
     
    # 创建一个密码管理者 
    password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
     
    # 添加用户名和密码 
     
    top_level_url = "https://example.com/foo/" 
     
    # 如果知道 realm, 我们可以使用他代替 ``None``. 
    # password_mgr.add_password(None, top_level_url, username, password) 
    password_mgr.add_password(None, top_level_url,'username','password'
     
    # 创建了一个新的handler 
    handler = urllib.request.HTTPBasicAuthHandler(password_mgr) 
     
    # 创建 "opener" (OpenerDirector 实例) 
    opener = urllib.request.build_opener(handler) 
     
    # 使用 opener 获取一个URL 
    x = opener.open(a_url) 
    print(x.read().decode("utf-8"))
     
    # 安装 opener. 
    # 现在所有调用 urllib.request.urlopen 将用我们的 opener. 
    urllib.request.install_opener(opener)

    此处代码为实例代码,用于说明Handler和Opener的使用方法。在这里,首先实例化了一个HTTPPasswordMgrWithDefaultRealm 对象,然后利用 add_password() 添加进用户名和密码,相当于建立了一个处理认证的处理器。接下来利用 urllib.request.build_opener() 方法来利用这个处理器构建一个 Opener ,那么这个 Opener 在发送请求的时候就具备了认证功能了。最后通过 Opener 的 open() 方法打开 URL,即可以完成认证。

    说明几点
    1.上面实例中,只将HTTPBasicAuthHandler提供给 build_opener 。
    2.默认情况下,opener可以处理一般情况的 handler—-ProxyHandler(已经设置了代理环境变量如 http_proxy)、UnknownHandlerHTTPHandlerHTTPDefaultErrorHandlerHTTPRedirectHandlerFTPHandlerFileHandlerDataHandlerHTTPErrorProcessor

    实际上,toplevel_url 要么是一个完整的 URL(包括“http:”模式部分以及主机名和可选的端口号)比如“https://example.com/”,要么是一个“authority”(即主机名和可选的端口号)例如“example.com”或“example.com:8080”(后者包含了端口号)。该“authority”如果出现的话,不能包含“用户信息(userinfo)“元素——如“joe@password:example.com” 是不被允许的。

    代理
    urllib 可以通过 ProxyHandler 自动检测你的代理设置并使用它们。当代理设置被检测时,它是普通 handler 的一部分。通常认为这是好事,当有些情况它也可能没有用。一个不用定义代理设置并使用它们的是创建自己的 ProxyHandler。这个实现方法类似于创建一个基本认证 handler。

    下面是一个实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #! /usr/bin/env python3
    import urllib.request
    proxy_handler = urllib.request.ProxyHandler({
    'socks5': 'localhost:1080'
    })
    opener = urllib.request.build_opener(proxy_handler)
    response = opener.open('https://www.baidu.com')
    print(response.read())

    在这里使用了 ProxyHandler ,ProxyHandler 函数接受一个字典类型的参数,其中key为协议名称,比如 http 还是 https 等,value为代理链接(包含 host 名称与端口号),也支持带验证的代理,可以添加多个代理。然后利用 build_opener() 方法利用这个 Handler 构造一个 Opener ,然后发送请求即可。

    Cookie设置

    获取百度 Cookie 实例如下

    1
    2
    3
    4
    5
    6
    7
    8
    #! /usr/bin/env python3
    import http.cookiejar, urllib.request
    cookie = http.cookiejar.CookieJar()
    handler = urllib.request.HTTPCookieProcessor(cookie)
    opener = urllib.request.build_opener(handler)
    response = opener.open('https://www.baidu.com')
    for item in cookie:
       print(item.name+"="+item.value)

    输出

    1
    2
    3
    4
    5
    6
    BAIDUID=37998CB10856532A8604B84ACFCAB6C0:FG=1
    BIDUPSID=37998CB10856532A8604B84ACFCAB6C0
    H_PS_PSSID=25576_1466_13289_21122_20928
    PSTM=1516720556
    BDSVRTM=0
    BD_HOME=0

    首先声明一个CookieJar对象,接下来利用HTTPCookieProcessor构建一个 handler ,最后利用 build_opener 方法构建出 opener ,执行 open() 即可。

    查看输出可以发现每一条 Cookie 有相应的名称和值。

    文本存储 Cookie 信息实例如下

    1
    2
    3
    4
    5
    6
    filename = 'cookie.txt'
    cookie = http.cookiejar.MozillaCookieJar(filename)
    handler = urllib.request.HTTPCookieProcessor(cookie)
    opener = urllib.request.build_opener(handler)
    response = opener.open('https://www.baidu.com')
    cookie.save(ignore_discard=True, ignore_expires=True)

    cookie.txt 文件内容为

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # Netscape HTTP Cookie File
    # https://curl.haxx.se/rfc/cookie_spec.html
    # This is a generated file!  Do not edit.
     
    .baidu.com  TRUE    /   FALSE   3664204558  BAIDUID 43896422C89528C1D912D69D7AA9CF49:FG=1
    .baidu.com  TRUE    /   FALSE   3664204558  BIDUPSID    43896422C89528C1D912D69D7AA9CF49
    .baidu.com  TRUE    /   FALSE       H_PS_PSSID  1458_21084_17001_20718
    .baidu.com  TRUE    /   FALSE   3664204558  PSTM    1516720911
    www.baidu.com   FALSE   /   FALSE       BDSVRTM 0
    www.baidu.com   FALSE   /   FALSE       BD_HOME 0

    相对单纯输出 Cookie ,这里 CookieJar 换成 MozillaCookieJarCookieJar 的子类) ,用于生成文件。MozillaCookieJar 可以用来处理 Cookie 以及和文件相关的事件,比如读取和保存 Cookie ,同时它可以将 Cookie 保存成 Mozilla 型的格式。

    此外,还有一个LWPCookieJar ,同样可以读取和保存 Cookie ,但是保存的格式和 MozillaCookieJar 的不一样,它会保存成 libwww-perl 的 Set-Cookie3 文件格式的 Cookie 。

    尝试一下,修改声明 cookie = http.cookiejar.LWPCookieJar(filename)
    新cookie.txt 文件内容为

    1
    2
    3
    4
    5
    6
    7
    #LWP-Cookies-2.0
    Set-Cookie3: BAIDUID="CDA35482887BF4DEAA078F12CD69DDD8:FG=1"; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2086-02-10 18:47:45Z"; version=0
    Set-Cookie3: BIDUPSID=CDA35482887BF4DEAA078F12CD69DDD8; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2086-02-10 18:47:45Z"; version=0
    Set-Cookie3: H_PS_PSSID=25641_1424_21108_17001; path="/"; domain=".baidu.com"; path_spec; domain_dot; discard; version=0
    Set-Cookie3: PSTM=1516721618; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2086-02-10 18:47:45Z"; version=0
    Set-Cookie3: BDSVRTM=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0
    Set-Cookie3: BD_HOME=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0

    以下为以 LWPCookieJar 格式为例实现对 Cookie 文件的读取与利用:

    1
    2
    3
    4
    5
    6
    cookie = http.cookiejar.LWPCookieJar()
    cookie.load('cookie.txt', ignore_discard=True, ignore_expires=True)
    handler = urllib.request.HTTPCookieProcessor(cookie)
    opener = urllib.request.build_opener(handler)
    response = opener.open('https://www.baidu.com')
    print(response.read().decode('utf-8'))

    前提是先利用上面的方式生成了 LWPCookieJar 格式的 Cookie 文件 ,然后利用 load() 方法,传入文件名称,构建 handler 和 opener 并能够正常输出百度网页的源代码。

    以上是关于 urllib.request 模块的常用知识以及重点内容的总结, 还具体说明了 urllib.request,urlopen() 的详细介绍以及用法。可以查看 python doc 。

    下面是 urllib.request 模块的其他 方法或者类的简要介绍:
    方法
    1. install_opener()

    urllib.request.install_opener(opener)

    安装一个 OpenerDirector实例作为全球默认的opener 。如果你想让 urlopen 使用这个opener,那么安装一个opener是必要的;否则可以简单地调用OpenerDirector.open()而不是urlopen()。这样代码不会检查一个真实的 OpenerDirector 并且任何类的适当的接口都可以运作。

    2.build_opener()

    urllib.request.build_opener([handler, …])

    返回一个顺序链的处理程序OpenerDirector的实例。处理程序可以是BaseHandler的实例,或者 BaseHandler 的子类(在这种情况下,必须调用没有参数的构造函数)。下面这些类的实例将提前处理程序,除非处理程序包含它们,或者它们子类的实例:ProxyHandler(如果检测到代理设置)、UnknownHandlerHTTPHandlerHTTPDefaultErrorHandlerHTTPRedirectHandlerFTPHandlerFileHandlerHTTPErrorProcessor

    如果 Python 安装 SSL 支持(即如果 ssl 模块可以被导入), HTTPSHandler 也将被添加。

    一个 BaseHandler 子类也可以通过改变它的 handler_order 属性来修改它再处理程序列表中的位置。

    3.pathname2url()

    urllib.request.pathname2url(path)

    将路径名转换成路径,从本地语法形式的路径中使用一个URL的路径组成部分。这不会产生一个完整的URL。它将返回引用 quote() 函数的值。

    4.url2pathname()

    urllib.request.url2pathname(path)

    将路径组件转换为本地路径的语法。这个不接受一个完整的URL。这个函数使用 unquote() 解码的通路。

    5.getproxies()

    urllib.request.getproxies()

    这个 helper 函数返回一个日程表 dictionary 去代理服务器的 URL 映射。扫描指定的环境变量 _proxy 大小写不敏感的方法,对所有的操作系统,当它不能找到它,从 Mac OS X 的 Mac OSX 系统配置和 Windows 系统注册表中寻找代理信息。如果两个大写和小写环境变量存在(或不一样),小写优先。

    请注意,如果环境变量 REQUEST_METHOD 已被设置,这通常表明你在 CGI 脚本运行环境,此时环境变量 HTTP_PROXY(大写 _PROXY) 将被忽略。这是因为该变量可以被客户端使用注射 “代理:” HTTP 头。如果你需要使用一个 HTTP 代理在 CGI 环境中,要么使用 ProxyHandler 明确,或者确保变量名小写(或至少是 _proxy后缀)。

    urllib.request.Request(url,data=None,headers={}, origin_req_host=None, unverifiable=False, method=None)

    1.这个类是一个抽象的 URL 请求。

    2.url 应该是一个字符串包含一个有效的 URL 。

    3.数据必须是一个字节对象指定额外的数据发送到服务器 或 None。如果没有这样的数据是必要的,数据也可能是一个 iterable 对象而且在这种情况下必须在最开始时指定内容的长度。目前 HTTP 是唯一一个这样请求数据的,当数据参数被提供时,HTTP 请求将会执行 POST 请求而不是 GET 请求。

    4.数据应该是一个缓冲的在标准应用程序中以x-www-form-urlencoded的格式。 urllib.parse.urlencode() 函数接受一个映射或序列集合,并返回一个 ASCII 文本字符串的格式。它应该在被用作数据参数之前,被编码为字节。

    5.headers 应该是一个字典,如果 add_header() 被称为与每个键和值作为参数。这通常是用来“恶搞” User-Agent 头的值,因为使用一个浏览器识别本身——一些常见HTTP服务器只允许请求来自浏览器而不是脚本。例如,Mozilla Firefox可能识别本身 “Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11”。而 urllib 默认的用户代理字符串 是”Python-urllib/2.6”在Python 2.6()。

    6.一个Content-Type header的例子: 用数据论证将发送一个字典 {“Content-Type”:”application/x-www-form-urlencoded”}。

    7.最后两个参数只是正确处理第三方 HTTP cookie:
    origin_req_host应该请求原始的主机交易,就像定义的 RFC 2965。它默认为 http.cookiejar.request_host(self)。这是原始请求的主机名或 IP 地址,由用户发起。例如。如果请求是一个图像在 HTML文档中,这应该是请求的请求主机包含图像的页面。

    8.无法核实的表明是否应该请求是无法核实的,这由 RFC 2965 定义。它默认为 False。一个无法核实的请求的 URL 的用户没有允许的选择。例如,如果请求是一个图像在一个HTML文档,和用户没有选择通过图像的自动抓取,这应该是正确的。

    9.这个方法应该是一个字符串,表示将使用(如 headers 请求头部信息)。如果提供,其值是存储在 method 属性和使用 get_method()。通过设置子类可能表明一个默认的方法 method类 本身的属性。

    urllib.request.OpenerDirector

    OpenerDirector 类打开 url 并通过 BaseHandler 连接在一起。它管理处理程序的连接,和恢复错误。

    urllib.request.BaseHandler

    这是对于所有已注册的处理程序的基类。

    urllib.request.HTTPRedirectHandler

    一个类来处理重定向。

    urllib.request.HTTPCookieProcessor(cookiejar=None)

    一个类来处理HTTP cookie。

    urllib.request.ProxyHandler(proxies=None)

    导致请求通过一个代理。如果代理是给定的,它必须是一个字典的代理协议名称映射到 ur l。默认值是从环境变量的列表 _proxy 中读取代理。如果没有代理设置环境变量,那么在 Windows 环境中代理设置了从注册表部分的网络设置,在 Mac OS X 环境代理信息检索的 OS X 系统配置框架。
    禁用一个代理传递一个空的字典。
    no_proxy 环境变量可以被用来指定主机不能通过代理;如果设置,它应该是一个以逗号分隔的主机名后缀。可选 :port 附加为例 cern.ch,ncsa.uiuc.edu,some.host:8080。

    请注意 :HTTP_PROXY 如果一个变量将被忽略 REQUEST_METHOD 设置;参见文档 getproxies()。

    urllib.request.HTTPPasswordMgr

    保持一个(realm, uri) -> (user, password) 映射的数据库 。

    urllib.request.HTTPPasswordMgrWithDefaultRealm

    保持一个 (realm, uri) -> (user, password) 映射的数据库 。如果没有其他搜索领域,一个值为 None 的领域 (realm) 被认为是一个全方位领域。

    urllib.request.HTTPPasswordMgrWithPriorAuth

    保持一个 HTTPPasswordMgrWithDefaultRealm 变量 还有一个uri -> is_authenticated 映射的数据库 。当发送身份认证可以马上使用 BasicAuth handler 确认身份, 而不是等待 401 报错响应。

    urllib.request.AbstractBasicAuthHandler(password_mgr=None)

    这是 mixin 类,处理远程主机身份认证和代理。使用 is_authenticated 值对于一个给定的URI 来决定是否发送请求来进行身份认证。如果 s_authenticated 返回 True 则发送凭证。如果 is_authenticated 是 False ,则凭证不发送。如果 返回 401 错误响应信息,则身份认证失败。如果身份验证成功, update_authenticated 被称为设置 True。

    urllib.request.HTTPBasicAuthHandler(password_mgr=None)

    处理远程主机的身份认证。

    urllib.request.ProxyBasicAuthHandler(password_mgr=None)

    处理身份认证与代理。

    urllib.request.AbstractDigestAuthHandler(password_mgr=None)

    这是 mixin 类,处理远程主机身份认证和代理。

    urllib.request.HTTPDigestAuthHandler(password_mgr=None)

    实现远程主机的身份认证。如果有password_mgr,应该是兼容HTTPPasswordMgr的;请参阅章节 HTTPPasswordMgr以获取很多接口信息。Digest认证处理器和基本认证处理器都被加入,Digest认证处理器总是首先进行验证。如果主机再次返回一个40X 响应,它发送到基本认证处理器进行处理。当出现除了 Digest 或基本身份的其他身份认证时,这个处理程序方法将提高 ValueError 3.3版本的变化:提高 ValueError不支持的身份验证方案。

    urllib.request.ProxyDigestAuthHandler(password_mgr=None)

    处理代理身份的验证。如果有password_mgr,应该是兼容HTTPPasswordMgr的;请参阅章节HTTPPasswordMgr 获取更多接口信息。

    urllib.request.HTTPHandler

    处理HTTP URLs。

    urllib.request.HTTPSHandler(debuglevel=0, context=None, check_hostname=None)

    处理开放的 HTTPS URLs 。在 http.client.HTTPSConnection 中 context 和 check_hostname 有相同的意义 。

    urllib.request.FileHandler

    打开本地文件。

    urllib.request.DataHandler

    开放数据 URLs。

    urllib.request.FTPHandler

    开放的 FTP URLs。

    urllib.request.CacheFTPHandler

    打开 FTP URLS,保持打开的 FTP 连接缓存来减少延迟。

    urllib.request.UnknownHandler

    全方位类处理未知的 URLs。

    urllib.request.HTTPErrorProcessor

    HTTP 错误响应过程。

    想了解更多Python关于爬虫、数据分析的内容,欢迎大家关注我的微信公众号:悟道Python

      

    转载于:https://www.cnblogs.com/ss-py/p/9492321.html

    展开全文
  • Python3中-爬虫库Urllib概述urllib.request1. urllib.request.Request2. urllib.request.urlopen3. urllib.request.urlopen和urllib.request.Request实例演示 概述 问:Urllib能做什么? 答:常用在爬虫开发、API...
  • Python3 urllib库的使用 request库 urllib中包括了四个模块,包括 urllib.request打开浏览url中内容 urllib.error包含从 urllib.request发生的错误或异常 urllib.parse解析url urllib.robotparser解析 robots.txt...
  • 1. urllib.request模块模块定义了身份验证、重定向、cookies等应用中打开Url(主要是HTTP)的函数类。1)urlopen方法def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,*, cafile=None, capath=...
  • 1.urllib2和urllib库的区别 ...在Python2.x中,分为Urllib库和Urllin2库,Python3.x之后都合并到Urllib库中了。实际开发中,用Requests多余urllib. 这里介绍使用的python3中的urllib库包括以下模块 urll...
  • Python3中urllib分为:urllib.request和urllib.parse import urllib.requesturl ="http://www.baidu.com/"#必须要完整格式 - 带上协议类型response = urllib.request.urlopen(url = url) #模拟浏览器向url发送...
  • Urllib库和URLError库的异常处理

    千次阅读 2018-04-30 23:52:27
    Urllib 是 Python 一个用于操作 URL 的模块, Python3 中合并了 Python2.X 中的 Urllib2 Urllib ,成为 Urllib 通过Urllib爬取网页 import urllib.request file=urllib.request.urlopen("...
  • 爬虫之urllib包以及request...Python3中将python2.7的urlliburllib2两个包合并成了一个urllib库 Python3中,urllib库包含有四个模块: urllib.request 主要用来打开或者读取url urllib.error 主要用来存放返回...
  • urllib 是 Python 的标准模块,它可以处理客户端的请求服务器端的响应,还可以解析 URL 地址。常用的模块为 request parse。request 模块是使用 socket 读取网络数据的接口,支持 HTTP、FTP 及 gopher 等连接...
  • urllib为python内置的HTTP请求,包含四个模块:request:最基本的HTTP请求模块, 只需要传入URL参数error:异常处理模块parse:工具模块,处理URL,拆分、解析合并等robotparser:识别robots.txt文件1....
  • 1. Python3 使用urllib库请求网络 1.1 基于urllib库的GET请求 请求百度首页www.baidu.com ,不添加请求头信息: 1 import urllib.requests 2 3 4 def get_page(): 5 url = 'http://www.baidu.com/' ...
  • urllib库

    2020-07-03 12:16:19
    声明:本文知识点解释部分大部分...在Python3的urllib库中,所有网络请求相关的方法,都被集成到了urllib.request模块下面了。 基本用法: from urllib import request # 从urllib导入request库 resp = request.url.
  • urllib库urllib库是Python...urlopen函数:在Python3的urllib库中,所有网络请求相关的方法,都被集到urllib.request模块下面了,以先来看下urlopen函数基本的使用:from urllib import requestresp = request.u...
  • python3下urllib.request库高级应用之Handle处理器自定义Openerpython3下urllib.request库高级应用之Handle处理器自定义Opener 经过前面对urllib.request库的频繁使用,都知道我们使用urllib库请求是都是使用...
  • 一、urllib库urllib是Python自带的一个用于爬虫的库,其主要作用就是可以通过代码模拟浏览器发送请求。其常被用到的子模块在Python3中的为urllib.request和urllib.parse,在Python2中是urlliburllib2。二、由易到...
  • Python3中将python2.7的urlliburllib2两个包合并成了一个urllib库 Python3中,urllib库包含有四个模块: urllib.request 主要用来打开或者读取url urllib.error 主要用来存放返回的错误信息 urllib.parse 主要...
  • 在python2中有urllib库和urllib2库来实现请求的发送,但在python3后统一为urllib库,由于urllib库是Python内置库,所以不需要额外安装下载。 request:最基本的HTTP請求模塊,用來模拟发送请求(如:在瀏覽器輸入網址...
  • urllib导入和urllib.request区别

    千次阅读 2018-06-10 10:24:41
    在Python2版本中,有urllib和urlib2两个可以用来实现request的发送。而在Python3中,已经不存在urllib2这个了,统一为urllib。变化:在Pytho2.x中使用import urllib2——-对应的,在Python3.x中会使用import ...
  • 在Python3中,有urllib库来实现请求的发送(将Python2中的urllib2已经统一至urllib库中)。 对于urllib库的疑问可以参照官网说明了解:https://docs.python.org/3/library/urllib.html urllib库 urllib库是python...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,010
精华内容 404
关键字:

urllib库和request库