爬虫基础——爬取动态网页与Cookie模拟登录
本文主讲:怎么爬取动态加载的页面及其Cookie模拟登录等等…..
爬取动态网页的操作流程!【重中之重】
目标:掌握爬取动态网页的操作流程
爬取动态网页的操作流程(浏览器控制台流程)
第一步:打开动态加载的网页
第二步:按下F12进行检查找到网络选项内的XHR栏等待抓包
第三步:刷新动态网页
第四步:对动态网页进行一些操作使异步加载的数据包加载出来(动态数据包也就是XHR内的数据包)
第五步:分析动态加载的数据包
第六步:利用python模拟发送请求!
爬取动态网页【重中之重】
目标:
1:掌握什么是动态网页
2:掌握抓取动态网页的步骤以及方法
3:掌握抓取动态网页的注意事项
什么是动态网页
答:动态网页应该具备下面其中一个特点
特点1:网页的数据在源代码中查不到(网页源代码内没有你要找的数据)(比如腾讯招聘)
特点2:当你在网页中点击下一页或者其他操作时,网页局部刷新(比如小米应用网)
特点3:当你在网页中进行一些操作时(滑动滑轮等),数据才加载出来(比如豆瓣电影)
动态网站:腾讯招聘、小米应用网、豆瓣电影、有道翻译等等
抓取动态网页的步骤以及方法(小米应用网为例——局部刷新的url网站)
第一步:按下F12进入检查,找到网络选项开始进行抓包
第二步:动态加载的数据包一般都是json格式的,对动态网页进行操作让数据加载出来,然后直接筛选XHR格式的数据包即可
第三步:分析XHR选项内的数据包,找到真正要抓取的那个数据包(包含数据的数据包)
第四步:分析请求的url以及请求方式,如果是get请求,着重分析查询参数,post请求着重分析Form_data,找到所有动态加载的数据包其中的规律
第五步:利用 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 | with open(“info.json”,“w”) as f: |
图示:
注意事项:
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 方法时程序会进入阻塞状态,回收完执行任务完毕的线程后才解除阻塞!
常用建立多线程语法截图
多线程爬虫的工作原理
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 | while not q.empty( ): |
判断队列内是否有数据,有数据才取,没数据不取
多线程对全局变量加线程锁的目的以及加锁步骤
加线程锁目的:多个线程共享(共同操作)一个全局变量时(全局文件变量、全局变量、全局队列变量),可能会产生资源竞争问题,这时就要对全局变量进行加线程锁,等一个线程对全局变量操作完全结束后,在进行线程锁的释放!,可避免多线程间资源的竞争
加线程锁步骤:
第一步: from threading import Lock
导入线程锁模块
第二步:l_obj = Lock()
创建一个线程锁
第三步:l_obj.acquire( )
某一个线程在对全局变量操作之前进行加锁
第四步:l_obj.release()
某一个线程在对全局变量操作完全结束后进行开锁
注意事项:对某个全局变量上线程锁,在线程锁未开锁之前,又给这个全局变量上了一把锁,这是程序会进入阻塞状态
图示:
不加线程锁造成的多线程间资源竞争问题
加线程锁解决多线程之间的资源竞争’
多线程爬虫共同操作全局变量【同一个资源】(文件变量、队列变量等)的注意事项:只要是线程对全局变量(同一个资源)进行了操作都要加上一把线程锁!!!
注意事项:全局变量(全局队列等)有几个,那么就要创建几把线程锁
单级页面的多线程爬虫框架【重中之重】
目标:掌握单级页面的多线程爬虫框架(各种函数)
多级页面的多线程爬虫框架【重中之重】
目标:掌握多级页面的多线程爬虫框架
Cookie模拟登陆【重点】
目标:
1:掌握Cookie是什么并且有什么用
2:掌握怎么用 Python程序实现Cookie模拟登陆(好几种方法)
Cookie是什么并且有什么用
Cookie适用场景:抓取需要登录才能获取数据的网站
答:当客户端向需要登录的网站服务器发送请求时,当登录成功后,服务器会给浏览器分发一段不超过4k大小的Cookie文本(浏览器将Cookie保存起来),服务器自身保存一段session文本,浏览器保存的Cookie相当于一个身份证,当你在向这个网站的其他页面发送请求时,会携带保存的Cookie,服务器会将浏览器发送请求时携带的Cookie与自身的session进行比对,比对成功后,放行(可以访问这个网站的其他页面),比对失败不放行(需要重新登录!)
怎么用 Python程序实现Cookie模拟登陆(好几种方法)
第一种方法:暴力模拟登录——手动查找 Cookie,将 Cookie 充当请求标头内 headers 的一个参数
第一步:浏览器打开需要登录的网站,先登录一次
第二步:登录成功后进入到待抓取数据的页面
第三步:按下F12找到网络选项,刷新页面,找到所有包里面的第一个包(一般是第一个包,主要是看这个包请求的url与目标url是否相同)
第四步:找到这个包里面请求信息(请求标头)的Cookie,复制
第五步:打开 pycharm 写程序发送请求
模拟Cookie登录的第二种方法——Cookies参数方式
方法:将手动抓取登录后的 Cookie 作为 requests 模块发送get请求的 cookies 参数传入
参数类型:字典 需要将抓取的cookie字符串处理为字典才能传参
语法:requests.get(url=url,headers=headers,cookies=cookies)
其中 cookies 就是处理好的 cookie字典
注意事项:手动抓取登录后的cookie和第一种方法抓取的一样!
截图:
将cookie字符串处理为cookies参数
第三种方法: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并保持会话,我们这是就可以向登录成功的任何页面发送请求获取数据了
未完待续……