爬虫基础——爬取动态网页与Cookie模拟登录

本文主讲:怎么爬取动态加载的页面及其Cookie模拟登录等等…..

爬取动态网页的操作流程!【重中之重】

目标:掌握爬取动态网页的操作流程

爬取动态网页的操作流程(浏览器控制台流程)

第一步:打开动态加载的网页

第二步:按下F12进行检查找到网络选项内的XHR栏等待抓包

第三步:刷新动态网页

第四步:对动态网页进行一些操作使异步加载的数据包加载出来(动态数据包也就是XHR内的数据包)

第五步:分析动态加载的数据包

第六步:利用python模拟发送请求!

爬取动态网页【重中之重】

目标:
1:掌握什么是动态网页
2:掌握抓取动态网页的步骤以及方法
3:掌握抓取动态网页的注意事项

什么是动态网页

答:动态网页应该具备下面其中一个特点

特点1:网页的数据在源代码中查不到(网页源代码内没有你要找的数据)(比如腾讯招聘)

特点2:当你在网页中点击下一页或者其他操作时,网页局部刷新(比如小米应用网)

特点3:当你在网页中进行一些操作时(滑动滑轮等),数据才加载出来(比如豆瓣电影)

动态网站:腾讯招聘、小米应用网、豆瓣电影、有道翻译等等

抓取动态网页的步骤以及方法(小米应用网为例——局部刷新的url网站)

第一步:按下F12进入检查,找到网络选项开始进行抓包

第二步:动态加载的数据包一般都是json格式的,对动态网页进行操作让数据加载出来,然后直接筛选XHR格式的数据包即可

image-20211013111214877

第三步:分析XHR选项内的数据包,找到真正要抓取的那个数据包(包含数据的数据包)

image-20211013111224434

第四步:分析请求的url以及请求方式,如果是get请求,着重分析查询参数,post请求着重分析Form_data,找到所有动态加载的数据包其中的规律

image-20211013111231314

第五步:利用 python 程序模拟浏览器向上面的 url 发送请求即可(构建查询参数)

抓取动态网页的注意事项

1:动态加载的网页其中动态加载的数据包一般都是json格式(python中的字典格式)的字符串

2:requests模块向目标url发送请求获取对象的 json 方法可以将 json 格式的字符串转换为 Python 格式的字典!

json解析模块的使用【重中之重】

目标:
1:掌握 json 标准库模块的使用场景
2:掌握 json 标准库模块的loads方法以及dump方法功能

json 标准库模块的使用场景

答:在抓取动态网页的异步加载的数据包时(XHR),网页服务器返回的数据包源代码是 json 格式的字符串,这时我们就要用到json解析模块来对这些json格式的字符串进行处理!!

json 标准库模块的 loads 方法以及 dump 方法功能

json.loads(json格式字符串)方法

功能:将 json 格式的字符串转换为 Python 格式的字典

参数:json格式的字符串(动态加载的数据包网页源代码)

图示:

json.dump(python,file,ensure_ascii = False)

功能:将Python格式的字典、列表 转换为 json 格式的字符串并且保存到 file 文件内(一般都是json后缀的文件)!

参数:

参数1:Python格式的列表、字典

参数2:待保存数据的文件名,一般是json后缀的文件

参数3(ensure_ascii):默认值为True,我们要给改为False,否则 json 格式的字符串包含中文保存到文件中,在文件内不会正常显示!

语法:

1
2
with open(“info.json”,“w”) as f:
json.dump(Python格式的字典、列表, f ,ensure_ascii = False

图示:

image-20211013111312698

注意事项:
1:loads方法有s,dump方法没有s
2:只要对文件进行操作就要利用with open打开文件

多线程爬虫【重中之重重】

目标:
1:掌握多进程以及多线程的适用场景
2:掌握创建多线程的步骤以及常用语法
3:掌握多线程爬虫的工作原理
4:掌握Python中队列的一些操作!
5:掌握多线程对全局变量加线程锁的目的

多进程以及多线程的适用场景

多进程适用场景:计算机密集型的操作(CPU密集型),比如说计算大量数据时,多进程可以保证同一时间多个进程同时工作,就是比较消耗内存

多线程适用场景:I/O密集型操作,比如说网络I/O、本地磁盘I/O,爬虫就是网络I/O与本地磁盘I/O(存储数据)结合体,多线程因为GIL的存在同一时间只能保证有一个线程在工作,但是也能保证同意时间肯定有一个线程在工作

创建多线程的步骤以及常用语法

步骤:

第一步:from threading import Thread 导入模块

第二步:t = Thread(target=任务函数名,args=()) 创建线程对象 args = (),是元组给任务函数传参,相当于位置传参

第三步:t.start() 启动线程

第四步:time.sleep(1) 等待线程任务执行完毕

第五步:t.join() 当 t 线程任务执行结束后 回收 t 这个线程(防止死线程的产生)

注意事项:

1:join()方法功能是等待创建的某线程执行任务函数结束后进行线程的回收

2:利用 join 方法时程序会进入阻塞状态,回收完执行任务完毕的线程后才解除阻塞!

常用建立多线程语法截图

image-20211013111344803

多线程爬虫的工作原理

image-20211013111354627

Python中队列的一些操作【数据存入、取出、取数据阻塞等问题】!

队列存入数据的优先级:队列中的数据是先进先出,从队尾进入,队首取出

操作队列的步骤:

第一步:from queue import Queue 导入队列模块

第二步:q = Queue() 创建q这个队列

第三步:q.put(存入队列的数据) 向q这个队列存入数据

第四步:q.get() 从q这个队列中取出存入的数据

第五步:q.empty() 判断队列中数据是否为空,是返回True,不是返回False

队列取数据出现的问题:当利用 get 方法从队列中取数据时,队列数据为空,那么程序就会进入阻塞状态,有什么办法让程序不阻塞嘛?

解决办法:
1:q.get(timeout=2) 设置阻塞时间,当超过两秒钟还未从队列中取得数据,程序直接报错

2:q.get(block=False) 在队列取不到数据直接报错,block默认值为True,也就是取不到数据程序一直处于阻塞状态

3:q.get_nowait() 利用get_nowait方法取数据,队列内没有数据直接报错!!

4:

1
2
while  not q.empty( ):     
q.get( )

判断队列内是否有数据,有数据才取,没数据不取

多线程对全局变量加线程锁的目的以及加锁步骤

加线程锁目的:多个线程共享(共同操作)一个全局变量时(全局文件变量、全局变量、全局队列变量),可能会产生资源竞争问题,这时就要对全局变量进行加线程锁,等一个线程对全局变量操作完全结束后,在进行线程锁的释放!,可避免多线程间资源的竞争

加线程锁步骤:

第一步: from threading import Lock 导入线程锁模块

第二步:l_obj = Lock() 创建一个线程锁

第三步:l_obj.acquire( ) 某一个线程在对全局变量操作之前进行加锁

第四步:l_obj.release() 某一个线程在对全局变量操作完全结束后进行开锁

注意事项:对某个全局变量上线程锁,在线程锁未开锁之前,又给这个全局变量上了一把锁,这是程序会进入阻塞状态

图示:

不加线程锁造成的多线程间资源竞争问题

image-20211013111448726

加线程锁解决多线程之间的资源竞争’

image-20211013111459472

多线程爬虫共同操作全局变量【同一个资源】(文件变量、队列变量等)的注意事项:只要是线程对全局变量(同一个资源)进行了操作都要加上一把线程锁!!!

注意事项:全局变量(全局队列等)有几个,那么就要创建几把线程锁

单级页面的多线程爬虫框架【重中之重】

目标:掌握单级页面的多线程爬虫框架(各种函数)

多级页面的多线程爬虫框架【重中之重】

目标:掌握多级页面的多线程爬虫框架

Cookie模拟登陆【重点】

目标:
1:掌握Cookie是什么并且有什么用
2:掌握怎么用 Python程序实现Cookie模拟登陆(好几种方法)

Cookie是什么并且有什么用

Cookie适用场景:抓取需要登录才能获取数据的网站

答:当客户端向需要登录的网站服务器发送请求时,当登录成功后,服务器会给浏览器分发一段不超过4k大小的Cookie文本(浏览器将Cookie保存起来),服务器自身保存一段session文本,浏览器保存的Cookie相当于一个身份证,当你在向这个网站的其他页面发送请求时,会携带保存的Cookie,服务器会将浏览器发送请求时携带的Cookie与自身的session进行比对,比对成功后,放行(可以访问这个网站的其他页面),比对失败不放行(需要重新登录!)

怎么用 Python程序实现Cookie模拟登陆(好几种方法)

第一种方法:暴力模拟登录——手动查找 Cookie,将 Cookie 充当请求标头内 headers 的一个参数

第一步:浏览器打开需要登录的网站,先登录一次

image-20211013111559051

第二步:登录成功后进入到待抓取数据的页面

image-20211013111605707

第三步:按下F12找到网络选项,刷新页面,找到所有包里面的第一个包(一般是第一个包,主要是看这个包请求的url与目标url是否相同)

image-20211013111613690

第四步:找到这个包里面请求信息(请求标头)的Cookie,复制

image-20211013111620460

第五步:打开 pycharm 写程序发送请求

image-20211013111627910

模拟Cookie登录的第二种方法——Cookies参数方式

方法:将手动抓取登录后的 Cookie 作为 requests 模块发送get请求的 cookies 参数传入

参数类型:字典 需要将抓取的cookie字符串处理为字典才能传参

语法:requests.get(url=url,headers=headers,cookies=cookies) 其中 cookies 就是处理好的 cookie字典

注意事项:手动抓取登录后的cookie和第一种方法抓取的一样!

截图:

image-20211013111641474

将cookie字符串处理为cookies参数

image-20211013111650257

第三种方法:requests模块的session类实现Cookie模拟登录

语法:

s = requests.session()创建session对象

s.post(url = url,headers = headers,data = data) 向登录网站的接口发送请求(get或者是post请求具体分析),进行登录网站

html = s.get(url = url,headers = headers).text

上一步成功实现后,s 对象就是已经携带了登录成功的Cookie并保持会话,我们这是就可以向登录成功的任何页面发送请求获取数据了

未完待续……