我们在这里也为正在找工作的同学精心准备了一套面试题,包含python以及爬虫等相关内容。更多python面试题后台发送python面试获取。
一、python常见面试题
1、简述any()和all()方法
any()只要迭代器中有一个元素为真就为真
all()迭代器中所有判断项返回都为真,结果才为真
(python中什么元素为假:0,空字符串、空列表、空字典、空元组、None、False)
2、python中copy()和deepcopy()区别
(1) 复制不可变数据类型,不管copy还是deepcopy,都是同一个地址当浅复制的值是不可变对象(数值,字符串,元组)时和=“赋值”的情况一样,对象的id值与浅复制原来的值相同。
(2) 复制的值是可变对象(列表和字典)
浅拷贝copy有两种情况:第一种情况:复制的 对象中无 复杂 子对象,原来值的改变并不会影响浅复制的值,同时浅复制的值改变也并不会影响原来的值。原来值的id值与浅复制原来的值不同。第二种情况:复制的对象中有 复杂 子对象(例如列表中的一个子元素是一个列表), 改变原来的值 中的复杂子对象的值 ,会影响浅复制的值。
深拷贝deepcopy:完全复制独立,包括内层列表和字典。
3、列出几种魔法方法并简要介绍用途
init:对象初始化方法
new:创建对象时候执行的方法,单列模式会用到
str:当使用print输出对象的时候,只要自己定义了str(self)方法,那么就会打印从在这个方法中return的数据
del:删除对象执行的方法
4、python内建数据类型有哪些
整型--int
布尔型--bool
字符串--str
列表--list
元组--tuple
字典--dict
5、可变类型和不可变类型
可变类型有list,dict.不可变类型有string,number,tuple. 当进行修改操作时,可变类型传递的是内存中的地址,也就是说,直接修改内存中的值,并没有开辟 新的内存。不可变类型被改变时,并没有改变原内存地址中的值,而是开辟一块新的内存,将原地址中的值复制 过去,对这块新开辟的内存中的值进行操作。
6、is和==有什么区别?
is:比较的是两个对象的id值是否相等,也就是比较俩对象是否为同一个实例对象。是否指向同一个内 存地址 == :比较的两个对象的内容/值是否相等,默认会调用对象的eq()方法
7、Python中类方法、类实例方法、静态方法有何区别?
类方法: 是类对象的方法,在定义时需要在上方使用 @classmethod 进行装饰,形参为cls,表示类对象, 类对象和实例对象都可调用 类实例方法: 是类实例化对象的方法,只有实例对象可以调用,形参为self,指代对象本身; 静态方法: 是一个任意函数,在其上方使用 @staticmethod 进行装饰,可以用对象直接调用,静态方法 实际上跟该类没有太大关系
8、内存泄露是什么?如何避免?
内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消 失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控 制,从而造成了内存的浪费。有 _del_() 函数的对象间的循环引用是导致内存泄露的主凶。不使用一个对象时使用: del object 来 删除一个对象的引用计数就可以有效防止内存泄露问题。通过Python扩展模块gc 来查看不能回收的对象的详细信息。可以通过 sys.getrefcount(obj) 来获取对象的引用计数,并根据返回值是否为0来判断是否内存泄露
9、python常见的列表推导式?
[表达式 for 变量 in 列表] 或者 [表达式 for 变量 in 列表 if 条件]
10、简述read、readline、readlines的区别?
read 读取整个文件 readline 读取下一行 readlines 读取整个文件到一个迭代器以供我们遍历
11、什么是Hash(散列函数)?
散列函数(英语:Hash function)又称散列算法、哈希函数,是一种从任何一种数据中创建小的数字 “指纹”的方法。散列函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。该函数 将数据打乱混合,重新创建一个叫做散列值(hash values,hash codes,hash sums,或hashes)的 指纹。散列值通常用一个短的随机字母和数字组成的字符串来代表
12、函数调用参数的传递方式是值传递还是引用传递?
Python的参数传递有:位置参数、默认参数、可变参数、关键字参数。函数的传值到底是值传递还是引用传递、要分情况:不可变参数用值传递:像整数和字符串这样的不可变对象,是通过拷贝进行传递的,因为你无论如何都 不可能在原处改变不可变对象。可变参数是引用传递:比如像列表,字典这样的对象是通过引用传递、和C语言里面的用指针传递数组 很相似,可变对象能在函数内部改变。
13、为什么函数名字可以当做参数用?
Python中一切皆对象,函数名是函数在内存中的空间,也是一个对象
14、Python中pass语句的作用是什么?
在编写代码时只写框架思路,具体实现还未编写就可以用pass进行占位,是程序不报错,不会进行任何 操作。
15、什么是lambda函数?有什么好处?
lambda 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的函数 1.lambda函数比较轻便,即用即仍,很适合需要完成一项功能,但是此功能只在此一处使用,连名字 都很随意的情况下 2.匿名函数,一般用来给filter,map这样的函数式编程服务 3.作为回调函数,传递给某些应用,比如消息处理
16、递归函数停止的条件?
递归的终止条件一般定义在递归函数内部,在递归调用前要做一个条件判断,根据判断的结果选择是继 续调用自身,还是return,返回终止递归。终止的条件:判断递归的次数是否达到某一限定值,判断运算的结果是否达到某个范围等,根据设计的目的来选择
17、生成器,迭代器的区别?
迭代器是遵循迭代协议的对象。用户可以使用 iter() 以从任何序列得到迭代器(如 list, tuple, dictionary, set 等)。另一个方法则是创建一个另一种形式的迭代器generator。要获取下一个元 素,则使用成员函数 next()(python2)P或函数 next() function(Python 3) 。当没有元素时,则引 发 StopIteration 此例外。若要实现自己的迭代器,则只要实现 next()(Python 2)或 __next__()(python3)
生成器(Generator),只是在需要返回数据的时候使用yield语句。每次next()被调用时,生成器会返 回它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值) 区别:生成器能做到迭代器能做的所有事,而且因为自动创建iter()和next()方法,生成器显得特别简 洁,而且生成器也是高效的,使用生成器表达式取代列表解析可以同时节省内存。除了创建和保存程序 状态的自动方法,当发生器终结时,还会自动抛出StopIteration异常
18、Python中yield的用法?
yield就是保存当前程序执行状态。你用for循环的时候,每次取一个元素的时候就会计算一次。用yield 的函数叫generator,和iterator一样,好处是不用一次计算所有元素,而是用一次算一次,可以节省很多空间,generator每次计算需要上一次计算结果,所以用yield,否则一return,上次计算结果就没了
19、谈谈你对多进程,多线程,以及协程的理解,项目是否用?
进程:一个运行的程序(代码)就是一个进程,没有运行的代码叫程序,进程是系统资源分配的最小单 位,进程拥有自己独立的内存空间,所有进程间数据不共享,开销大。线程: cpu调度执行的最小单位,也叫执行路径,不能独立存在,依赖进程存在,一个进程至少有一个线 程,叫主线程,而多个线程共享内存(数据共享,共享全局变量),从而极大地提高了程序的运行效率。协程: 是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和 栈,直接操中栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
20、Python异步使用场景有那些?
异步的使用场景: 1、 不涉及共享资源,获对共享资源只读,即非互斥操作 2、 没有时序上的严格关系 3、 不需要原子操作,或可以通过其他方式控制原子性 4、 常用于IO操作等耗时操作,因为比较影响客户体验和使用性能 5、 不影响主线程逻辑
21、当Python退出时,是否会清除所有分配的内存?
答案是否。当Python退出时,对其他对象具有循环引用的Python模块,以及从全局名称空间引用的对象不会被解除分配或释放。无法解除分配C库保留的那些内存部分。退出时,由于拥有自己的高效清理机制,Python会尝试取消分配/销毁其他所有对象。
22、Python中如何实现多线程?
Python是多线程语言,其内置有多线程工具包。多线程能让我们一次执行多个线程。Python中的GIL(全局解释器锁)确保一次执行单个线程。一个线程保存GIL并在将其传递给下个线程之前执行一些操作,看上去像并行运行的错觉。事实上是线程在CPU上轮流运行。所有的传递会增加程序执行的内存压力。
23、Python中的闭包是什么?
当一个嵌套函数在其外部区域引用了一个值时,该嵌套函数就是一个闭包。其意义就是会记录这个值
24、Python的优势有哪些?
Python 易于学习
完全支持面向对象
高效的高级数据结构,可用少量代码构建出多种功能
拥有最成熟的程序包资源库之一
跨平台而且开源
25、Python中append,insert和extend的区别?
append:在列表末尾添加新元素。
insert:在列表的特定位置添加元素。
extend:通过添加新列表来扩展列表。
26、break、continue、pass是什么
break:在满足条件时,它将导致程序退出循环。
continue:将返回到循环的开头,它使程序在当前循环迭代中的跳过所有剩余语句。
pass:使程序传递所有剩余语句而不执行。
27、区分Python中的remove,del和pop?
remove:将删除列表中的第一个匹配值,它以值作为参数。
del:使用索引删除元素,它不返回任何值。
pop:将删除列表中顶部的元素,并返回列表的顶部元素。
二、爬虫常见面试题
1、列举您使用过的Python网络爬虫所用到的网络数据包?
requests, urllib,urllib2, httplib2
2、你用过的爬虫框架或者模块有哪些?优缺点?
Python自带:urllib,urllib2 第三方:requests 框架:Scrapy urllib 和urllib2模块都做与请求URL相关的操作,但他们提供不同的功能。urllib2: urllib2.urlopen可以接受一个Request对象或者url,(在接受Request对象时,并以此可以来设置 一个URL的headers),urllib.urlopen只接收一个url。urllib 有urlencode,urllib2没有,因此总是urllib, urllib2常会一起使用的原因 scrapy是封装起来的框架,他包含了下载器,解析器,日志及异常处理,基于多线程,twisted的方式 处理,对于固定单个网站的爬取开发,有优势,但是对于多网站爬取100个网站,并发及分布式处理不 够灵活,不便调整与扩展 requests是一个HTTP库,它只是用来请求,它是一个强大的库,下载,解析全部自己处理,灵活性高 Scrapy优点:异步,xpath,强大的统计和log系统,支持不同url。shell方便独立调试。写middleware 方便过滤。通过管道存入数据库
3、一些反爬及其应对措施
(1)通过user-agent来判断是否是爬虫。
解决方案:可以通过伪装请求头中的user-agent来解决。若user-agent被检测到,可以找大量的user-agent,放入列表,然后进行更换
(2)将IP进行封杀。
解决方案:可以通过代理来伪装IP。
(3)通过访问频率来判断是否是一个爬虫。
解决方案:可以通过设置请求间隔,和爬取间隔。
(4)当一定时间内的总请求数超过上限,弹出验证码。
解决方案:对于简单的验证码图片可以使用tesseract来处理,对于复杂的可以去打码平台。
(5)通过JS来获取页面数据。
解决方案:可以使用selenium+phantomjs来加载JS获取数据。
4、搜索引擎的工作流程(通用爬虫的工作流程)
(1)抓取网页:通过搜索引擎将待爬取的URL加入到通用爬虫的URL队列中,进行网页内容的爬取。
(2)数据存储:将爬取下来的网页保存到本地,这个过程会有一定的去重操作,如果某个网页的内 容大部分内容都会重复,搜索引擎可能不会保存。
(3)预处理:提取文字,中文分词,消除噪音(比如版权声明文字,导航条,广告等)。
(4)设置网站排名,为用户提供服务。
5、HTTP协议和HTTPS协议的区别
HTTP协议是使用明文数据传输的网络协议,明文传输会让用户存在一个非常大的安全隐患。端口80
HTTPS协议可以理解为HTTP协议的安全升级版,就是在HTTP的基础上增加了数据加密。端口443
HTTPS协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议要比HTTP协议安全。
6、客户端请求(Get和Post区别)
(1)组成:请求行、请求头部、空行、请求数据四个部分组成
(2)请求方法Get/Post
(3)Get和Post的区别
GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。
(4)常见的请求头
User-Agent:客户端请求标识。
Accept:传输文件类型。
Referer :请求来源。
cookie (cookie):在做登录的时候需要封装这个头。
Content-Type (POST数据类型)
7、服务器响应
(1)组成:状态行,响应头,空行,响应正文。
(2)常见的响应头
Content-Type:text/html;资源文件的类型,还有字符编码
Content-Length:响应长度
Content-Size响应大小
Content-Encoding告诉客户端,服务端发送的资源是采用什么编码的。
Connection:keep-alive这个字段作为回应客户端的Connection:keep-alive,告诉客户端服务器的tcp连接也是一个长连接,客户端可以继续使用这个TCP连接发送HTTP请求。
8、爬虫可以解决的问题:
(1)解决冷启动问题
(2)搜索引擎的根基:做搜索引擎少不了爬虫
(3)建立知识图谱,帮助建立机器学习知识图谱
(4)可以制作各种商品的比价软件,趋势分析。
9、爬虫分类
(1)通用爬虫:搜索引擎的主要组成,作用就是将互联网的上页面整体的爬取下来之后,保存到本地。
(2)聚焦爬虫:聚焦爬虫在实施网页抓取时会对内容进行处理筛选,尽量保证只抓取与需求相关的网页信息。通用爬虫和聚焦爬虫的区别:聚焦爬虫在实施网页抓取时会对内容进行处理筛选,尽量保证只抓取与需求相关的网页信息。
10、爬虫遵循的协议:robot协议
定义:网络爬虫排除标准。
作用:告诉搜索引擎哪里可以爬,哪里不可以爬。
11、Cookie和Session
产生原因:由于HTTP是一个无状态的协议,每次请求如果需要之前的一些信息,无法记录,因此为了解决这个问题,产生了一种记录状态技术,Cookie和Session。
Cookie指某些网站为了辨别用户身份,进行会话跟踪而存储在用户本地终端上的数据,种类有会话Cookie和持久Cookie。
(1)会话Cookie指存在浏览器内存的Cookie,当浏览器关闭,会话Cookie会失效;
(2)持久Cookie是保存在硬盘上的Cookie。
Session用来存储特定的用户会话所需的属性及其配置信息。
Cookie是在客户端记录状态,Session是在服务端记录状态。
联系:当客户端发送一个Cookie,服务器会从这个Cookie中找到sessionID,再查找出相应的Session信息返回给客户端,来进行用户页面的流转。如果通过sessionID来查找Session的时候,发现没有Session(一般第一次登陆或者清空了浏览器),那么就会创建一个Session。
12、response的常用属性
1.获取字符串类型的响应正文:response.text
2.获取bytes类型的响应正文:response.content
3.响应正文字符串编码:response.encoding
4.状态码:response.status_code5.响应头:response.headers
13、response.text乱码问题
#方法一:转换成utf-8格式
response.encoding='utf-8'
print(response.text)
#方法二:解码为utf-8 :
with open('index.html','w',encoding='utf-8') as fp: fp.write(response.content.decode('utf-8'))
14、JSON使用
(1)json.dumps(Python的list或者dict),将Python的list或者dict返回为一个JSON字符串;
(2)json.loads(json字符串),将JSON字符串返回为Python的list或者dict;
(3)json.dump(list/dict,fp),将Python的list或者dict转为一个JSON字符串,保存到文件中;
(4)json.load(fp) ,从JSON文件中读出JSON数据,并转换为Python的list或者dict。
15、XML的基本知识
1.定义:XML称为可拓展性标记语言,类似 HTML;
2.特点:XML具有自描述特性,是一种半结构化数据;
3.作用:XML的设计宗旨是传输数据,而非显示数据。可以作为配置文件使用来记录一些重要信息;
4.XML的标签需要我们自行定义。
16、HTML和XML 区别
语法方面:
在HTML中不区分大小写,在XML中严格区分大小写
在HTML中,在某些情况可以省略闭合标签。在XML中,绝对不能省略任何标记。
在XML中,单标签结尾处需要加’/’。
XML文档中,空白部分不会被解析器自动删除,但是HTML是过滤掉空格的
在XML中,属性值必须封装在引号中。在HTML中,引号可用可不用。
在HTML中属性名可以不带属性值,XML必须带属性值而且不能为空。
标记不同:
HTML使用固有的标记,XML没有固有标记。
作用不同:
XML主要用来传输数据,HTML主要用来显示数据
17、实现模拟登录的方式有哪些
1.直接使用已知的Cookie访问
先用浏览器登录,获取浏览器里的cookie字符串,然后封装至请求头。
2.模拟登录后用session保持登录状态
使用session模拟登陆后,就会自动存储一个cookie次从而保持住登录状态。
3.使用Selenium+PhantomJS访问
Selenium库提供了find_element(s)_by_xxx的方法来找到网页中的输入框、按钮等元素。其中xxx可以是id、name、tag_name(标签名)、class_name(class),也可以是xpath(xpath表达式)等等。当然还是要具体分析网页源代码。
18、写爬虫是用多进程好?还是多线程好?为什么?
IO密集型情况使用多线程;
计算密集型情况下使用多进程;
IO 密集型代码(文件处理、网络爬虫等),多线程能够有效提升效率(单线程下有 IO 操作会进行 IO 等待,造成不必要的时间浪费,而开启多线程能在线程 A 等待时,自动切换到线程 B,可以不浪费 CPU 的资源,从而能提升程序执行效率)。在实际的数据采集过程中,既考虑网速和响应的问题,也需要考虑自身 机器的硬件情况,来设置多进程或多线程。
19、怎么监控爬虫的状态
(1)使用 Python 的 STMP 包将爬虫的状态信心发送到指定的邮箱。
(2)Scrapyd、pyspider
(3)引入日志
20、你用过的爬虫框架或者模块有哪些?优缺点?
1.Scrapy Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。用这个框架可以轻松爬下来如亚马逊商品信息之类的数据。
2.Beautiful Soup Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间
21、需要登录的网页,如何解决同时限制ip,cookie,session
解决限制IP可以使用代理IP地址池、服务器;不适用动态爬取的情况下可以使用反编译JS文件获取相应的文件,或者换用其它平台(比如手机端)看看是否可以获取相应的json文件。
22、验证码的解决?
1.输入式验证码 解决思路:这种是最简单的一种,只要识别出里面的内容,然后填入到输入框中即可。这种识别技术叫OCR,这里我们推荐使用Python的第三方库,tesserocr。对于没有什么背影影响的验证码,直接通过这个库来识别就可以。但是对于有嘈杂的背景的验证码这种,直接识别识别率会很低,遇到这种我们就得需要先处理一下图片,先对图片进行灰度化,然后再进行二值化,再去识别,这样识别率会大大提高。
验证码识别大概步骤
转化成灰度图
去背景噪声
图片分割
2.滑动式验证码 解决思路:对于这种验证码就比较复杂一点,但也是有相应的办法。我们直接想到的就是模拟人去拖动验证码的行为,点击按钮,然后看到了缺口 的位置,最后把拼图拖到缺口位置处完成验证。
第一步:点击按钮。然后我们发现,在你没有点击按钮的时候那个缺口和拼图是没有出现的,点击后才出现,这为我们找到缺口的位置提供了灵感。
第二步:拖到缺口位置。我们知道拼图应该拖到缺口处,但是这个距离如果用数值来表示?通过我们第一步观察到的现象,我们可以找到缺口的位置。这里我们可以比较两张图的像素,设置一个基准值,如果某个位置的差值超过了基准值,那我们就找到了这两张图片不一样的位置,当然我们是从那块拼图的右侧开始并且从左到右,找到第一个不一样的位置时就结束,这是的位置应该是缺口的left,所以我们使用selenium拖到这个位置即可。这里还有个疑问就是如何能自动的保存这两张图?这里我们可以先找到这个标签,然后获取它的location和size,然后 top,bottom,left,right = location['y'] ,location['y']+size['height']+ location['x'] + size['width'] ,然后截图,最后抠图填入这四个位置就行。具体的使用可以查看selenium文档,点击按钮前抠张图,点击后再抠张图。最后拖动的时候要需要模拟人的行为,先加速然后减速。因为这种验证码有行为特征检测,人是不可能做到一直匀速的,否则它就判定为是机器在拖动,这样就无法通过验证了。
3.点击式的图文验证 和 图标选择 图文验证:通过文字提醒用户点击图中相同字的位置进行验证。
图标选择:给出一组图片,按要求点击其中一张或者多张。借用万物识别的难度阻挡机器。
这两种原理相似,只不过是一个是给出文字,点击图片中的文字,一个是给出图片,点出内容相同的图片。
这两种没有特别好的方法,只能借助第三方识别接口来识别出相同的内容,推荐一个超级鹰,把验证码发过去,会返回相应的点击坐标。
然后再使用selenium模拟点击即可。具体怎么获取图片和上面方法一样。
23、“极验”滑动验证码如何破解?
破解核心思路:1、如何确定滑块滑动的距离?滑块滑动的距离,需要检测验证码图片的缺口位置 滑动距离 = 终点坐标 - 起点坐标 然后问题转化为我们需要屏幕截图,根据selenium中的position方法并进行一些坐标计算,获取我们需要的位置
2、坐标我们如何获取?起点坐标:每次运行程序,位置固定不变,滑块左边界离验证码图片左边界有6px的距离 终点坐标:每次运行程序,位置会变,我们需要计算每次缺口的位置 怎么计算终点也就是缺口的位置?先举个例子,比如我下面两个图片都是120x60的图片,一个是纯色的图片,一个是有一个蓝色线条的图片(蓝色线条位置我事先设定的是60px位置),我现在让你通过程序确定蓝色线条的位置,你怎么确定?
答案:遍历所有像素点色值,找出色值不一样的点的位置来确定蓝色线条的位置
24、爬虫多久爬一次,爬下来的数据是怎么存储?
以json格式存储到文本文件 这是最简单,最方便,最使用的存储方式,json格式保证你在打开文件时,可以直观的检查所存储的数据,一条数据存储一行,这种方式适用于爬取数据量比较小的情况,后续的读取分析也是很方便的。
存储到excel 如果爬取的数据很容易被整理成表格的形式,那么存储到excel是一个比较不错的选择,打开excel后,对数据的观察更加方便,excel也可以做一些简单的操作,写excel可以使用xlwt这个库,读取excel可以使用xlrd,同方法1一样,存储到excel里的数据不宜过多,此外,如果你是多线程爬取,不可能用多线程去写excel,这是一个限制。
存储到sqlite sqlite无需安装,是零配置数据库,这一点相比于mysql要轻便太多了,语法方面,只要你会mysql,操作sqlite就没有问题。当爬虫数据量很大时,需要持久化存储,而你又懒得安装mysql时,sqlite绝对是最佳选择,不多呢,它不支持多进程读写,因此不适合多进程爬虫。
存储到mysql数据库 mysql可以远程访问,而sqlite不可以,这意味着你可以将数据存储到远程服务器主机上,当数据量非常大时,自然要选择mysql而不是sqlite,但不论是mysql还是sqlite,存储数据前都要先建表,根据要抓取的数据结构和内容,定义字段,这是一个需要耐心和精力的事情。
存储到mongodb 我最喜欢no sql 数据库的一个原因就在于不需要像关系型数据库那样去定义表结构,因为定义表结构很麻烦啊,要确定字段的类型,varchar 类型数据还要定义长度,你定义的小了,数据太长就会截断。mongodb 以文档方式存储数据,你使用pymongo这个库,可以直接将数据以json格式写入mongodb, 即便是同一个collection,对数据的格式也是没有要求的,实在是太灵活了。刚刚抓下来的数据,通常需要二次清洗才能使用,如果你用关系型数据库存储数据,第一次就需要定义好表结构,清洗以后,恐怕还需要定义个表结构,将清洗后的数据重新存储,这样过于繁琐,使用mongodb,免去了反复定义表结构的过程。
25、cookie过期的处理问题?
这时候就需要cookie自动的更新了。通常怎样自动更新cookie呢?这里会用到selenium。步骤1、 采用selenium自动登录获取cookie,保存到文件; 步骤2、 读取cookie,比较cookie的有效期,若过期则再次执行步骤1;步骤3、 在请求其他网页时,填入cookie,实现登录状态的保持。
如果本文对你有帮助,别忘记给我个3连 ,点赞,转发,评论,
咱们下期见!答案获取方式:已赞 已评 已关~
学习更多知识与技巧,关注与私信博主(03)