• 【Python爬虫】HTTP基础和urllib库、requests库的使用


    引言:

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

    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)主体是可选数据块,可包含文本或二进制数据,也可为空。

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

    请求报文格式

    <method><request-URL><version>
    <headers>
    
    <entity-body>

    响应报文格式

    <version><status><reason-phrase>
    <headers>
    
    <entity-body>
    

    一个获取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 import request, error, parse
    
    
    try:
        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'))
    
    except error.HTTPError as e:
        print('http error.')
    except error.URLError as e:
        print('url error')

    urllib.error.HTTPError和urllib.error.URLError

    from urllib import request, error
    
    
    try:
        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'))
    except error.HTTPError as e:
        print('http error.')
    except error.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权威指南》

    “解读爬虫中HTTP的秘密”

    Requests文档

  • 相关阅读:
    win7下virtualbox遇到的问题
    2.5年, 从0到阿里
    TCP/IP入门(4) --应用层
    TCP/IP入门(3) --传输层
    TCP/IP入门(2) --网络层
    TCP/IP入门(1) --链路层
    Socket编程实践(13) --UNIX域协议
    Socket编程实践(12) --UDP编程基础
    Socket编程实践(10) --select的限制与poll的使用
    Socket编程实践(9) --套接字IO超时设置方法
  • 原文地址:https://www.cnblogs.com/pusidun/p/8563248.html
Copyright © 2020-2023  润新知