爬虫实战4—多线程与多进程爬虫

文章说明:本文是在学习一个网络爬虫课程时所做笔记,文章如有不对的地方,欢迎指出,积极讨论。

一、表单及登录

登录的核心是为了获得cookie,登录成功后,header会有设置cookie的相关信息,此时我们需要把服务器返回的cookie信息,写入到我们后续请求的header的cookie里。

(一)HTML提交数据:

(1)form表单

由浏览器实现post方法

表单类型(主要):form-data和x-www-form-urlencoded

(2)ajax请求

用JavaScript对网页进行处理,一般以JSON方式提交数据

(二)获取并设置Cookie

二、多线程及语言分析对比

(一)多线程爬虫

进程(process):是指正在运行的程序的实例。

第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量

运行中的进程可能具有以下三种基本状态:

1)就绪状态(Ready):进程已获得除处理器外的所需资源,等待分配处理器资源;只要分配了处理器进程就可执行。

2)运行状态(Running):进程占用处理器资源。

3)阻塞状态(Blocked):由于进程等待某种条件(如I/O操作或进程同步),在条件满足之前无法继续执行。该事件发生前即使把处理器资源分配给该进程,也无法执行。

第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时OS执行之),它才能成为一个活动的实体,我们称其为进程。

线程(thread):有时被称为轻量级进程(LightWeightProcess,LWP),是程序执行流的最小单元。一个标准的线程由线程ID、当前指令指针(PC)、寄存器集合(registers)和堆栈组成。线程是进程中的一个实体,是被系统独立调度和分派的基本单位。

在单个程序中同时运行多个线程完成不同的工作,称为多线程

把进程作为分配资源的基本单位,把线程作为独立运行和独立调度的基本单位。

意外:当遇到网页登录后,返回302跳转的情况下,urllib的response会丢失Set-Cookie信息,导致登录不成功,因此我们需要一个通用的能处理Cookie的工具(CookieJar)来:

1.自动处理Set-Cookie请求

2.自动处理过期的Cookie

3.自动在对应域下发送特殊的cookie

爬虫实战4—多线程与多进程爬虫

三、多线程爬虫(更轻,更快,不太可靠)

(一)多线程的复杂性

1.资源、数据的安全性:锁保护

2.原子性:数据操作是天然互斥的

3.同步等待:wait()notify() notifyAll() 

爬虫实战4—多线程与多进程爬虫

4.死锁:多个线程对资源互锁,造成死锁

5.容灾:任何线程出现错误,整个进程都会停止

(二)Python线程

1.支持多线程(JavaScript、PHP不支持多线程)

2.Python线程直接映射到native线程

3.GIL(globalinterpretor lock):对于多核的利用能力有限

(三)实现一个多线程爬虫

1.创建一个线程池threads=[]

2.确认URL队列线程安全Queue Deque

3.从队列取出uURL,分配一个线程开始爬取pop()/get()  threading.Thread

4.如果线程池满了,循环等待,直到有线程结束 t.is_alive()

5.从线程池移除已经完成下载的线程threads.remove(t)

6.如果当前级别的URL已经遍历完成,t.join()函数等待所有现场结束,然后开始下一级别的爬取

使用threading,做了封装、容灾等,使用更安全

而非thread,更底层,安全性比较低

(四)pythonMySQL connector

使用MySQLConnectionPool来管理多线程下的mysql数据库连接。

(五)多线程爬虫评价:

优势:

1)有效利用CPU时间

2)极大减小下载出错、阻塞对抓取速度的影响,整体上提高下载的速度

3)对于没有反爬虫限制的网站,下载速度可以多倍增加

局限性:

1)对于有反爬的网站,速度提升有限

2)提高了复杂度,对编码要求更高

3)线程越多,每个线程获得的时间就越少,同时线程切换更频繁也带来额外开销

4)线程之间资源竞争更激烈

线程与进程

四、多进程爬虫(更重,更慢,可靠)

多进程爬虫可以认为是分布式爬虫的基础,在单机上也可以用。因为一般大型的网站的服务器都是采用分布式部署的,可以采用多进程同时在不同的服务器器上进行爬取。

(一)进程间通信

主要是socket:可以标准化,可以用于多机

socket:网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

(二)Android进程间通信AIDL(AndroidInterface Difinition Language,Android接口定义语言)

Android系统中的进程不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。

Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现

(三)创建多进程爬虫

(1)采用c/s模式:运行速度快;扩展方便。

(2)采用DB模式:开发便捷,DB本身具备读写保护及支持IPC;只需写一个爬虫程序。