《python3网络爬虫开发实战》第一章总结

1.1 HTTP基本原理

1.1.1 URL

        URL(Universal Resource Locator)为统一资源定位符,简单地说URL就是web地址,俗称“网址”。构成如下:

scheme://[username:password@]hostname[:port][/path][;parameters][?query][#fragment]

1.1.2 HTTP和HTTPS

        HTTP(Hypertext Transfer Protocol)为超文本传输协议,其作用为把超文本数据从网络传输到本地浏览器。能够保证高效而准确的传输超文本文档。

        HTTPS就是安全的HTTP(HTTP+SSL层),HTTP的安全基础是SSL。(SSL (Secure Sockets Layer)安全套接层。是由Netscape公司于1990年开发,用于保障Word Wide Web(WWW)通讯的安全。主要任务是提供私密性,信息完整性和身份认证。)

        HTTPS已大势所趋。

1.1.3 HTTP请求过程

        在客户端(比如手机和电脑)的浏览器地址栏输入URL,回车可看到相应内容。该过程由浏览器往网站所在服务器发送请求,网站服务器收到请求后处理,返回对应的相应给到浏览器。

        如图,打开一个网页,右键后选择“检查”,即可打开浏览器的开发者工具。选到“网络”选项,然后刷新网页,可以看到多个条目,其中一个条目就代表一次发送请求和接收响应的过程。

1.1.4 请求

        请求,英文为Request, 由客户端发往服务器,分为四部分内容:请求方法(Request Method)、请求的网址(Request URL)、请求头(Request Headers)、请求体( Request Body)。

1.请求方法

        常见的请求方法有两种: GET和POST。POST请求大多在提交表单时发起。例如,对于一个登录表单,输人用户名和密码后,单击“登录”按钮,这时通常会发起一个POST请求,其数据通常以表单的形式传输,而不会体现在URL中。

        登录时一般需要提交用户名和密码,其中密码是敏感信息,如果使用GET方式请求,密码就会暴露在URL里面,造成密码泄露,所以这时候最好以POST方式发送。上传文件时,由于文件内容比较大,因此也会选用POST方式。

2.请求的网址
3.请求头

        包括cookie等;cookie,也常用复数形式Cookies,这是网站为了辨别用户,进行会话跟踪而存储在用户本地的数据。它的主要功能是维持当前访问会话。

4.请求体

        请求体,一般承载的内容是POST请求中的表单数据,对于GET请求,请求体为空。

1.1.5 响应

        响应,即Response,由服务器返回给客户端,可以分为三部分:响应状态码( Response Status Code)、响应头( Response Headers )、响应体( Response Body )。

1.1.6 HTTP2.0

1.二进制分帧层

        HTTP 2.0 所有性能增强的核心就在于这个新的二进制分帧层。简而言之,HTTP 2.0将HTTP协议通信分解为二进制编码帧的交换,这些帧对应着特定数据流中的消息,所有这些都在一个TCP连接内复用,这是HTTP 2.0协议所有其他功能和性能优化的基础。

2.多路复用
3.流控制

        流控制是一种阻止发送方向接收方发送大量数据的机制,以免超出后者的需求或处理能力。

4.服务器推送

        HTTP 2.0新增的另一个强大的功能是:服务器可以对一个客户端请求发送多个响应。换句话说,除了对最初请求的响应外,服务器还可以向客户端推送额外资源,而无须客户端明确地请求。

1.2 Web网页基础

1.2.1 网页的组成

        网页可以分为三大部分:HTML、CSS和、javaScript。如果把网页比作一个人,那么HTML相当于骨架、JavaScript 相当于肌肉、css相当于皮肤,这三者结合起来才能形成一个完善的网页。下面我们分别介绍一下这三部分的功能。

        HTML ( Hypertext Markup Language)中文翻译为超文本标记语言;下图为最简单的HTML示例。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>This is a Demo</title>
</head>
<body>
    <div id=" container">
        <div class= " wrapper">
            <h2 class="title" >Hello World</h2>
            <p class= ”text" >Hello, this is a paragraph.</p>
        </div>
    </div>
</body>
</html>

        CSS,全称叫作Cascading Style Sheets,即层叠样式表,常用于修饰HTML。

        JavaScript简称JS,是一种脚本语言。HTML和CSS组合使用,提供给用户的只是一种静态信息缺乏交互性。JavaScript 的出现使得用户与信息之间不只是一-种浏览与显示的关系,还实现了一种实时、动态、交互的页面功能。

1.2.2 网页的结构

        上面的HTML实例test.html效果如图。

1.2.3 节点树及节点间的关系

1.2.4 CSS选择器(重要)

        CSS选择器会为不同的节点设置不同的样式规则。常用的有#id,#开头代表选择id,后面接id的名称;.class,点代表选择class,后面是class的名称;还有一种选择方式,就是根据标签名,例如想选择二级标题,直接用h2即可。

        另外,CSS选择器还支持嵌套选择,利用空格把各个选择器分隔开便可以代表嵌套关系,如
#container .wrapper p代表先选择id为container的节点,然后选择其内部class为wrapper的节点,再进一步选择该节点内部的p节点。要是各个选择器之间不加空格,则代表并列关系,如div#container .wrapper p. text代表先选择id为container的div节点,然后选择其内部class为wrapper的节点,再进一步选择这个节点内部的class为text的p节点。

1.3 爬虫的基本原理

1.3.1爬虫概述

        步骤大概为获取网页---提取信息---保存数据---自动化程序。

1. 获取网页

        爬虫的工作首先是获取网页,这里就是获取网页的源代码。源代码里包含网页的部分有用信息,所以只要获取源代码,就可以从中提取想要的信息了。

2. 提取信息

        要用到第三章学到的xpath、BeautifulSoup、pyquery等选择方法。

3. 保存数据

        在第四章学到,即可以保存为txt、json文本,可以用Mysql、MongoDB等数据库储存。

4. 自动化程序

        写出好的代码让爬取网页上的信息更高效。

1.3.2 能爬怎样的数据

        最常爬HTML;有些网页返回的JSON字符串也能爬,例如下面的代码,在IP地址的后面加上了post后,返回的就是JSON文本了。

response = urllib.request.urlopen('https://www.httpbin.org/post',data=data)
print(response.read().decode('utf-8'))

        当然还可以抓取二进制数据、扩展名文件等。

1.3.3 JavaScript渲染的页面

        有时候,我们在用urllib或requests抓取网页时,得到的源代码和在浏览器中实际看到的不一样。现在有越来越多的网页是采用Ajax(第五章学到)、前端模块化工具构建的,可能整个网页都是由JavaScript渲染出来的,也就是说原始的HTML代码就是一个空壳。

        所以在用urlib或requests等库请求当前页面时,我们得到的只是HTML代码,它不会继续加载
JavaScript文件,我们也就无法看到完整的页面内容。

1.4 Session和Cookie

1.4.1 静态网页和动态网页

        将之前给出的最简单的那串html代码保存到.html文件中,然后找到该文件的路径,在浏览器输入后就能以文件形式打开,效果如图。

        如果把这个文件放在某台具有固定公网IP的主机上,在这台主机上安装Apache或Nginx等服务器,然后该主机就可以作为服务器了,其他人可以通过访问服务器看到那个实例页面,这就搭建了一个最简单的网站。

        这种网页的内容是由HTML代码编写的,文字、图片等内容均通过写好的HTML代码来指定,这种页面叫作静态网页。静态网页加载速度快、编写简单,同时也存在很大的缺陷,如可维护性差、不能根据URL灵活多变地显示内容等。如果我们想给静态网页的URL传人一个name参数,让其在网页中显示出来,是无法做到的。

        于是动态网页应运而生,它可以动态解析URL中参数的变化,关联数据库并动态呈现不同的页面内容,非常灵活多变。我们现在看到的网站几乎都是动态网站,它们不再是一个简单的HTML页面,可能是由JSP、PHP、Python 等语言编写的,功能要比静态网页强大、丰富太多。此外,动态网站还可以实现用户登录和注册的功能。

        现在网站上很多页面是需要登录之后才可以查看的。按照一般的逻辑,输人用户名和密码登录网站,肯定是拿到了一种类似凭证的东西,有了这个凭证,才能保持登录状态,访问那些登录之后才能看得到的页面。这种神秘的凭证到底是什么呢?其实它就是Session和Cookie共同产生的结果。

1.4.2 无状态HTTP

        HTTP的无状态是指HTTP协议对事务处理是没有记忆能力的,或者说服务器并不知道客户端处于什么状态。客户端向服务器发送请求后,服务器解析此请求,然后返回对应的响应,服务器负责完成这个过程,而且这个过程是完全独立的,服务器不会记录前后状态的变化,也就是缺少状态记录。这意味着之后如果需要处理前面的信息,客户端就必须重传,导致需要额外传递一些重复请求,才能获取后续响应,这种效果显然不是我们想要的。为了保持前后状态,肯定不能让客户端将前面的请求全部重传一次,这太浪费资源了,对于需要用户登录的页面来说,更是棘手。

        这时,两种用于保持HTTP连接状态的技术出现了,分别是Session和Cookie。Session在服务端,也就是网站的服务器,用来保存用户的Session信息; Cookie 在客户端,也可以理解为在浏览器端,有了Cookie,浏览器在下次访问相同网页时就会自动附带上它,并发送给服务器,服务器通过识别Cookie鉴定出是哪个用户在访问,然后判断此用户是否处于登录状态,并返回对应的响应。可以这样理解,Cookie里保存着登录的凭证,客户端在下次请求时只需要将其携带上,就不必重新输人用户名、密码等信息重新登录了。

1.4.3 Session

        Session,中文称之为会话,其本义是指有始有终的一系列动作、消息。例如打电话时,从拿起电话拨号到挂断电话之间的一系列过程就可以称为一个Session。
        而在Web中,Session 对象用来存储特定用户Session所需的属性及配置信息。这样,当用户在应用程序的页面之间跳转时,存储在Session对象中的变量将不会丢失,会在整个用户Session中一直存在下去。当用户请求来自应用程序的页面时,如果该用户还没有Session,那么Web服务器将自动创建一个Session对象。当Session过期或被放弃后,服务器将终止该Session。

1.4.4 Cookie

        Cookie,指某些网站为了鉴别用户身份、进行Session跟踪而存储在用户本地终端上的数据。

1. Session维持

        那么,怎样利用Cookie保持状态呢?在客户端第一次请求服务器时,服务器会返回一个响应头中带有Set-Cookie字段的响应给客户端,这个字段用来标记用户。客户端浏览器会把Cookie保存起来,当下一次请求相同的网站时,把保存的Cookie放到请求头中一起提交给服务器。Cookie 中携带着Session ID相关信息,服务器通过检查Cookie即可找到对应的Session,继而通过判Session辨认用户状态。如果Session当前是有效的,就证明用户处于登录状态,此时服务器返回登录之后才可以查看的网页内容,浏览器再进行解析便可以看到了。
        反之,如果传给服务器的Cookie是无效的,或者Session已经过期了,客户端将不能继续访问页面,此时可能会收到错误的响应或者跳转到登录页面重新登录。
        Cookie和Session需要配合,一个在客户端,一个在服务端,二者共同协作,就实现了登录控制。

2. 属性结构

        下图以bilibili为例,在浏览者开发工具中打开Application(应用程序)选项卡,找到左边的storage(存储),最后一项即为cookies。注意右边列表的列名,即一些属性,比如下面的Max-Age属性。

3. 会话cookie和持久cookie

        从表面意思来看,会话Cookie就是把Cookie放在浏览器内存里,关闭浏览器之后,Cookie即失效;持久Cookie则会把Cookie保存到客户端的硬盘中,下次还可以继续使用,用于长久保持用户的登录状态。

         严格来说,其实没有会话Cookie和持久Cookie之分,只是Max-Age或Expires字段决定了Cookie失效的时间。

        Max-Age:Cookie失效的时间,单位为秒,常和Expires一起使用,通过此属性可以计算出Cookie的有效时间。Max-Age 如果为正数,则表示Cookie在Max-Age秒之后失效;如果为负数,则Cookie在关闭浏览器时失效,而且浏览器不会以任何形式保存该Cookie。

        因此,一些持久化登录的网站实际上就是把Cookie的有效时间和Session有效期设置得比较长,下次客户端再访问页面时仍然携带之前的Cookie,就可以直接呈现登录状态。

1.4.5 常见误区

        关闭浏览器后,消失的不是Session,而是cookie;就好像生活中的会员卡,没有顾客的要求,店家不会轻易删除顾客资料。

        大部分网站使用会话Cookie来保存Session ID信息,而浏览器关闭后Cookie就消失了,当浏览器再次连接服务器时,就无法找到原来的Session了。

        如果把服务器设置的Cookie保存到硬盘上,或者使用某种手段改写浏览器发出的HTTP请求头,把原来的Cookie发送给服务器,那么再次打开浏览器时,仍然能够找到原来的Session ID,依旧保持登录状态。

        而且恰恰是由于关闭浏览器不会导致Session被删除,因此需要服务器为Session设置一个失效时间,当距离客户端上一次使用Session的时间超过这个失效时间时,服务器才可以认为客户端已经停止了活动,并删除掉Session以节省存储空间。(每次使用Session时,这个失效时间又会重新开始算起)

1.5 代理的基本原理

        代理实际上就是指代理服务器,英文叫作Proxy Server,功能是代网络用户取得网络信息。形象点说,代理是网络信息的中转站。当客户端正常请求一个网站时,是把请求发送给了Web服务器,Web服务器再把响应传回给客户端。设置代理服务器,就是在客户端和服务器之间搭建一座桥,此时客户端并非直接向Web服务器发起请求,而是把请求发送给代理服务器,然后由代理服务器把请求发送给Web服务器,Web服务器返回的响应也是由代理服务器转发给客户端的。这样客户端同样可以正常访问网页,而且这个过程中Web服务器识别出的真实IP就不再是客户端的IP了,成功实现了IP伪装,这就是代理的基本原理。

        代理的主要作用包括:

        1. 突破自身IP的访问限制,访问一些平时不能访问的站点。

        2. 访问一些单位或团体的内部资源。比如,使用教育网内地址段的免费代理服务器,就可以下载和上传对教育网开放的各类FTP,也可以查询、共享各类资料等。

        3. 提高访问速度。

        4. 隐藏真实IP。

1.6 多线程和多进程的基本原理

1.6.1 多线程的含义

        进程可以理解为一个可以独立运行的程序单位,例如打开一个浏览器就开启了一个浏览器进程;进程就是线程的集合,进程是由一个或多个线程构成的,线程是操作系统进行运算调度的最小单位,是进程中的最小运行单元。在一个进程中,可以同时处理很多事情,例如在浏览器进程中,可以在多个选项卡中打开多个页面,有的页面播放音乐,有的页面播放视频,这些任务可以同时运行,互不干扰。为什么能做到同时运行这么多任务呢,其实一个任务就对应一个线程。以上面说的浏览器进程为例,其中的播放音乐就是一个线程,播放视频也是一个线程。

1.6.2 并发和并行

        说到多进程和多线程,不得不再介绍两个名词一并 发和并行。我们知道,在计算机中运行一个程序,底层是通过处理器运行一条条指令来实现的。

        处理器同一时刻只能执行一条指令,并发(concurrency)是指多个线程对应的多条指令被快速轮换地执行。例如一个处理器,它先执行线程A的指令一段时间,再执行线程B的指令一段时间, 然后再切回线程A执行一段时间。处理器执行指令的速度和切换线程的速度都非常快,人完全感知不到计算机在这个过程中还切换了多个线程的上下文,这使得多个线程从宏观上看起来是同时在运行。从微观上看,处理器连续不断地在多个线程之间切换和执行,每个线程的执行都--定会占用这个处理器的一个时间片段,因此同一时刻其实只有一个线程被执行。

        并行(parallel)指同一时刻有多条指令在多个处理器上同时执行,这意味着并行必须依赖多个处理器。不论是从宏观还是微观上看,多个线程都是在同一时刻一起执行的。并行只能存在于多处理器系统中,因此如果计算机处理器只有一个核,就不可能实现并行。而并发在单处理器和多处理器系统中都可以存在,因为仅靠一个核,就可以实现并发。

1.6.3 多线程适用场景

        在一个程序的进程中,有一些操作是比较耗时或者需要等待的,例如等待数据库查询结果的返回、等待网页的响应。这时如果使用单线程,处理器必须等这些操作完成之后才能继续执行其他操作,但在这个等待的过程中,处理器明显可以去执行其他操作。如果使用多线程,处理器就可以在某个线程处于等待态的时候,去执行其他线程,从而提高整体的执行效率。

        很多情况和上述场景一样,线程在执行过程中需要等待。网络爬虫就是一个非常典型的例子,爬虫在向服务器发起请求之后,有一段时间必须等待服务器返回响应,这种任务就属于IO密集型任务。

        但并不是所有任务都属于IO密集型任务,还有一种任务叫作计算密集型任务,也可以称为CPU密集型任务。顾名思义,就是任务的运行一直需要处理器的参与。

        如果是IO密集型任务,使用多线程能够大大提高程序整体的爬取效率;如果是计算密集型任务,由于运行任务一直需要处理器的参与,多线程并不会节省整体的时间,因为需要处理的任务的计算总量是不变的。此时要是线程数目过多,反而还会在线程切换的过程中耗费更多时间,使得整体效率变低。

1.6.4 多线程的含义

        进程(process)是具有一定独立功能的程序在某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位。顾名思义,多进程就是同时运行多个进程。由于进程就是线程的集合,而且进程是由一个或多个线程构成的,所以多进程意味着有大于等于进程数量的线程在同时运行。

1.6.5 Python中的多线程和多进程

        Python 中的全局解释器锁(GIL)限制了同一时间只能有一个线程执行 Python 字节码的情况。这就意味着在多线程的情况下,多个线程不能真正并行执行 Python 代码。

        而在多进程模型中,每个进程都有自己的解释器和内存空间,因此不存在 GIL 的竞争,可以实现真正的并行执行。

        不过,对于爬虫这种IO密集型任务来说,多线程和多进程产生的影响差别并不大。但对于计算密集型任务来说,由于GIL的存在,Python多线程的整体运行效率在多核情况下可能反而比单核更低。而Python的多进程相比多线程,运行效率在多核情况下比单核会有成倍提升。

        IO密集型任务:多线程提高效率,且多进程与多线程效果差别不大;

        计算密集型任务:多线程降低效率,且多进程明显优于多线程。

        从整体来看,Python的多进程比多线程更有优势。所以,如果条件允许的话,尽量用多进程。
 

        




        


        

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值