关于Python爬虫常见的面试题

文章目录

一、介绍爬虫

1.爬虫定义

自动的抓取互联网上信息的脚本文件。

2.爬虫遵循的协议

定义:robot协议(网络爬虫排除标准)
作用:告诉搜索引擎哪里可以爬,哪里不可以爬

3.爬虫可以解决的问题

(1)解决冷启动问题
(2)做搜索引擎少不了爬虫
(3)可以对爬取的数据进行数据分析

4.爬虫分类

  • 通用爬虫:搜索引擎的主要组成,作用就是将互联网的上页面整体的爬取下来之后,保存到本地。
  • 聚焦爬虫:聚焦爬虫在实施网页抓取时会对内容进行处理筛选,尽量保证只抓取与需求相关的网页信息。

5.常见反爬及其应对措施总结

( 1)通过user-agent来判断是否是爬虫

通过伪装请求头中的user-agent来解决。若user-agent被检测到,可以找一些常见的的user-agent放入列表,然后每次爬取随机选一个。

(2)通过访问频率来判断是否是一个爬虫。

可以通过设置请求时间间隔。

(3)爬取频繁将ip进行封禁。

使用代理IP来解决

扫描二维码关注公众号,回复: 13170396 查看本文章

(4)当一定时间内的总请求数超过上限,弹出验证码

  • 简单的图形验证码:可以使用tesseract来处理,也可以使用最新的一个muggle_ocr来处理,识别率还凑合。对于复杂的可以去打码平台。
  • 滑块验证码:通过selenium+浏览器获取滑块的滑动间距,然后捕捉滑块按钮,按照人体的规律(一般是先快后慢)拖动滑块
  • 其他验证码:打码平台解决

(5)cookie限制

  • 1对于cookie有效时间长的,可以通过手动登录,然后把cookie添加至headers里
  • 2.对于cookie有效时间短的,爬虫每次启动时可以通过selenium登录后获取cookie,然后放到headers里
  • 其他须知:
    ①有的cookie登录前后字符串不变,可能是对方网站后台加的判断
    ②有的cookie和设备是进行绑定的,可通过多个设备机器进行解决
    ③有的cookie和IP进行绑定,可通过代理ip解决

(6)js加密

  • 1.可以使用selenium+phantomjs来加载js获取数据
  • 2.通过浏览器的debug来逐步搞清参数生成逻辑(常见的有无限debugger,js混淆等等)

二、介绍搜索引擎

1.搜索引擎的工作流程(通用爬虫的工作流程)

  1. 抓取网页:通过搜索引擎将待爬取的url加入到通用爬虫的url队列中,进行网页内容的爬取

  2. 数据存储:将爬取下来的网页保存到本地,这个过程会有一定的去重操作,如果某个网页的内 容大部分内容都会重复,搜索引擎可能不会保存

  3. 预处理:提取文字,中文分词,消除噪音(比如版权声明文字,导航条,广告等)

  4. 设置网站排名,为用户提供服务

2.搜索引擎的局限性

  1. 搜索引擎只能爬取原网页,但是页面90%内容都是无用的
  2. 通用搜索引擎只能爬取文字信息,不能对音频、图片等进行爬取
  3. 只能基于关键字查询,无法基于语义查询

三、介绍http

0.网络七层协议

在这里插入图片描述

1.http协议特点

  • http协议是超文本传输协议
  • http协议是一个应用层协议
  • 无连接:每次请求都是独立的。
  • 无状态:表示客户端每次请求都不能记录请求状态,就是两条请求直接不可通信

2.http工作过程

  • 地址进行DNS解析,将url解析出对应的内容
  • 封装http请求数据包
  • 封装成TCP包,建立TCP连接(TCP的三次握手)
  • 客户端发送请求
  • 服务器接收请求,发送响应
  • 客户端接收到响应,进行页面渲染
  • 服务器关闭tcp连接(TCP的四次挥手)

3.http协议和https协议的区别

  • http协议是使用明文数据传输的网络协议,明文传输会让用户存在一个非常大的安全隐患。端口80
  • HTTPS协议为HTTP协议的安全升级版,就是在HTTP的基础上增加了数据加密。端口443
  • HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议 要比http 协议安全

4.http通信

http通信由两部分组成:客户端请求消息 与 服务器响应消息

5.关于响应常见的响应码

状态码 意义 常见举例1 常见举例2
1xx 表示服务器成功接收部分请求,要求客户端继续提交其余请求才能完成整个处理过程 100 :服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求 101 :服务器将遵从客户的请求转换到另外一种协议
2xx 表示服务器成功接收请求并已完成整个处理过程 200:OK 请求成功 201 :请求被创建完成,同时新的资源被创建
3xx 重定向 302:所请求的页面已经临时转移至新的url 303 :所请求的页面可在别的url下被找到
4xx 客户端错误 403:对被请求页面的访问被禁止 404:服务器无法找到被请求的页面
5xx 服务器错误 500:请求未完成。服务器遇到不可预知的情况 504 :网关超时。

6.客户端请求(get和post区别)

①组成:请求行、请求头部、空行、请求数据四个部分组成

②常见的请求方法:get/post

③get和post的区别

GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。

get post
get是从服务器获取数据 post是向服务器提交数据
get参数拼接在url后面,这样是明文传输,很不安全。 post的参数放在body体内,相比get比较安全
get提交可以被浏览器缓存 post不会被浏览器缓存
get产生一个TCP数据包(对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据)) POST产生两个TCP数据包(而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 (返回数据))
传输大小会受限 参数是放在是实体里面,而且参数大小不会受限

④常见的请求头

User-Agent:客户端请求标识。
Accept: 传输文件类型。
Referer :请求来源。
cookie (cookie):在做登录的时候需要封装这个头。
Content-Type (POST数据类型)

7.服务器响应

①组成:状态行,响应头,空行,响应正文。

②常见的响应头

Content-Type:text/html;资源文件的类型,还有字符编码
Content-Length:响应长度
Content-Size响应大小
Content-Encoding告诉客户端,服务端发送的资源是采用什么编码的。
Connection:keep-alive这个字段作为回应客户端的Connection:keep-alive,告诉客户端服务器的tcp连接也是一个长连接,客户端可以继续使用这个tcp连接发送http请求

四、url:统一资源定位符

基本格式:scheme://host[:port#]/path/…/?query-string
协议://服务器ip地址:端口号/资源路径/?key1=参数1&key2=参数2

五、当在浏览器输入一个url,为什么可以加载出一个页面?为什么抓包的过程中请求一个url,出现很多的资源请求?

  • 当我们在浏览器输入一个url,客户端会发送这个url对应的一个请求到服务器获取内容
  • 服务器收到这个请求,解析出对应内容,之后将内容封装到响应里发送到客户端
  • 当客户端拿到这个html页面,会查看这个页面中是否有css、js、image等url,如果有,在分别进行请求,获取到这些资源。
  • 客户端会通过html的语法,将获取到的所有内容完美的显示出来。

六、介绍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。

七、 hashlib密码加密

def get_hex(value): 
	md5_ = hashlib.md5()
    md5_.update(value.encode('utf-8')) 
    return md5_.hexdigest() 

八、关于response.text乱码问题

①response的常用属性

1.获取字符串类型的响应正文: response.text
2.获取bytes类型的响应正文: response.content
3.响应正文字符串编码:response.encoding
4.状态码:response.status_code
5.响应头:response.headers

②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')) 

九、介绍代理

1.代理的作用

  • 突破自身IP访问限制, 访问一些平时不能访问的站点。
  • 访问一些单位或团体内部资源: 比如使用教育网内地址段免费代理服务器, 就可以用于对教育网开放的各类FTP 下载上传, 以及各类资料查询共享等服务。
  • 提高访问速度: 通常代理服务器都设置一个较大的硬盘缓冲区,当有外界的信息通过时,同时也将其保存到缓冲区中,当其他用户再访问相同的信息时,则直接由缓冲区中取屮信息传给用户,以提高访问速度。
  • 隐藏真实IP : 上网者也可以通过这种方法隐藏自己的IP ,免受攻击。对于爬虫来说,我们用代理就是为了隐藏自身IP,防止自身的被封锁。

2.代理根据匿名程度的分类

代理 介绍
高度匿名代理 会将数据包原封不动地转发, 在服务端看来就好像真的是一个普通客户端在访问, 而记录的IP 是代理服务器的IPO
普通匿名代理 会在数据包上做一些改动, 服务端上有可能发现这是个代理服务器, 也有一定几率追查到客户端的真实伊代理服务器通常会加人的HITP 头有HTTP_VIA 和HTTP_X_FORWARDED FOR 。
透明代理 不但改动了数据包, 还会告诉服务器客户端的真实IPO 这种代理除了能用缓存技术提高浏览速度, 能用内容过滤提高安全性之外, 并无其他显著作用, 最常见的例子是内网中的硬件防火墙。
间谍代理 指组织或个人创建的用于记录用户传输的数据, 然后进行研究、监控等目的的代理服务器。

十、介绍json数据

1.数据的分类

种类 特点
结构化数据 数据以行为为单位,一行数据表示一个实体信息,每一行的数据饿属性是相同的。常见关系型数据库中以表存储的数据就是结构化数据
半结构化数据 结构化数据的一种形式,并不符合关系型数据库或其他数据表的形式关联起来的数据模型结构,但包含相关标记,用来分隔个语义元素以及对记录和字段进行分层,因此也被称为自描述的结构。常见的半结构化数据有:xml,html,json
非结构化数据 1.没有固定的结构,常见的非结构化数据有:文档,图片和视频等。 2.对于非结构数据,一般我们整体存储二进制格式

2.json的本质

json是一个字符串,json是对js对象的字符串表达式,它使用文本形式表示一个JS对象的信息。

3. json使用

1)json.dumps(list/dict)   将python的list或者dict返回为一个json字符串
(2)json.dump(list/dict,fp)   将python的list或者dict转为一个json字符串,保存到文件中

(3)json.loads(json字符串)    将json字符串返回为python的list或者dict4)json.load(fp)            从json文件中读出json数据,并转换为python的list或者dict

十一、正则表达式

1.贪婪和非贪婪

  • 正则默认是贪婪模式,所以数量控制符默认是取最大值,也是贪婪。例如*
  • 非贪婪是用?来控制,尽量匹配最少的次数,0次或一次

2.python使用格式:

pattern=re.compile('正则表达式') 
print(pattern.match(字符串,start,end))#默认从头开始匹配,只匹配一次,返回一个match对象
print(pattern.search(字符串,start,end))#从任意位置开始匹配,只匹配一次,返回一个match对象
print(pattern.findall(字符串,start,end))#全文多次匹配,将匹配到的结果放到一个list返回给我们
print(pattern.finditer(字符串,start,end))#全文多次匹配,将匹配到的结果放到一个match对象的迭代器返回

3.常见的正则题目

在这里插入图片描述

十二、介绍xml

1.xml的基本知识

  • 定义:xml称为可拓展性标记语言,类似 HTML
  • 特点:xml具有自描述特性,是一种半结构化数据
  • 作用:XML 的设计宗旨是传输数据,而非显示数据。可以作为配置文件使用来记录一些重要信息。
  • 注意:XmL 的标签需要我们自行定义。

2.html和xml区别

语法方面:

  • 在html中不区分大小写,在xml中严格区分大小写
  • 在html中,在某些情况可以省略闭合标签。在xml中,绝对不能省略任何标记。
  • 在xml中,单标签结尾处需要加’/’。
  • xml文档中,空白部分不会被解析器自动删除,但是html是过滤掉空格的
  • 在xml中,属性值必须封装在引号中。在html中,引号可用可不用。
  • 在html中属性名可以不带属性值,xml必须带属性值而且不能为空

标记不同:

  • html使用固有的标记,xml没有固有标记

作用不同

  • xml主要用来传输数据,html主要用来显示数据

十三、selenium+phantomjs

  • Selenium 是一个 Web 的自动化测试工具,可以根据我们的指令,让浏览 器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是 否发生。
  • Selenium 自己不带浏览器,不支持浏览器的功能,它需要与第三方浏 览器结合在一起才能使用。但是我们有时候需要让它内嵌在代码中运行, 所以 我们可以用一个PhantomJS 的工具代替真实的浏览器。
  • Selenium 库里有个 叫 WebDriver 的 API。WebDriver 有点儿像可以加载网站的浏览器,但是它也可以查找页面元素,与页面上的元 素进行交互 (发送文本、点击等),以及执行其他动作来运行网络爬虫。
  • PhantomJS 是一个基于 Webkit 的无界面浏览器,它会把网站加载到内存并执行页面上的 js,因为不会展示图形界面,所以运行起来比完整的浏览器要高效。相比传统的 Chrome或 Firefox 浏览器等,资源 消耗会更少。
  • 如果我们把 Selenium 和 PhantomJS 结合在一起,就可以运行一个非常强 大的网络爬虫了,这个爬虫可以处理 js、Cookie、headers,以及任 何我们真实用户需要做的事情。主程序退出后,selenium 不保证 phantomJS 也成功退出。
  • WebDriverWait 虽然可能会减少延时,但是目前存在 bug(各种报错),这种 情况可以采用 sleep。

十四、实现模拟登录的方式有哪些

1.直接使用已知的cookie访问

先用浏览器登录,获取浏览器里的cookie字符串,然后封装至请求头

2.模拟登录后用session保持登录状态

使用session模拟登陆后,就会自动存储一个cookie次从而保持住登录状态

3.使用selenium+phantomjs访问

这个爬虫可以处理 js、Cookie、headers,以及任 何我们真实用户需要做的事情。

十五、线程+进程+多线程

1.定义

名字 定义 python中的类名 通信 状态
线程 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。 threading 通过队列Queue 新建-就绪–运行-阻塞-死亡
进程 一个程序的执行实例就是一个进程。每一个进程提供执行程序所需的所有资源。(进程本质上是资源的集合)一个进程有至少一个线程。 multiprocessing 通过队列Queue 新建-就绪–运行-阻塞-死亡

2.进程与线程区别

  1. 同一个进程中的线程共享同一内存空间,但是进程之间是独立的。
  2. 同一个进程中的所有线程的数据是共享的,进程之间的数据是独立的
  3. 对主线程的修改可能会影响其他线程的行为,但是父进程的修改(除了删除以外)不会影响其他子进程。
  4. 线程是一个上下文的执行指令,而进程则是与运算相关的一簇资源。
  5. 同一个进程的线程之间可以直接通信,但是进程之间的交流需要借助中间代理来实现。
  6. 创建新的线程很容易,但是创建新的进程需要对父进程做一次复制。
  7. 一个线程可以操作同一进程的其他线程,但是进程只能操作其子进程。
  8. 线程启动速度快,进程启动速度慢(但是两者运行速度没有可比性)。
  9. IO密集型用多线程,CPU密集型用多进程

3.协程

yield:线程和进程的操作是由程序触发系统接口,最后的执行者是系统,它本质上是操作系统提供的功能。而协程的操作则是程序员指定的,在python中通过yield,人为的实现并发处理。

协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时。协程,则只使用一个线程,分解一个线程成为多个“微线程”,在一个线程中规定某个代码块的执行顺序。

协程的适用场景:当程序中存在大量不需要CPU的操作时(即IO使用较多情况下)。

常用第三方模块: gevent和greenlet。(gevent是对greenlet的高级封装,一般用它就行,是一个相当高效的模块。)

4.互斥锁

定义:当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制。线程同步能够保证多个线程安全访问“竞争资源”,最简单的同步机制就是引用互斥锁。

由于线程共享进程的内存空间和数据,因此在某个线程要共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进入写入操作,从而保证了多线程情况下数据的正确性。互斥锁体现的就是一个同步的机制,即该线程释放资源就是一个条件,条件完成,才能执行下一步操作。是微观的操作

锁的好处:

  • 确保了某段代码只能由一个线程从头到尾完整地执行。
  • 全局变量的安全

锁的坏处:

  • (1)阻止了多线程的并发执行,包含锁的某段代码实际上只能以单线程模块执行,效率降低
  • (2)由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁的时,可能会造成“死锁”。

5.死锁

  • (1)同一个线程先后两次调用lock,在第二次调用时,由于锁已经被自己占用,该线程会挂起等待自己释放锁,由于该线程已被挂起而没有机会释放锁,因此 它将一直处于挂起等待状态,变为死锁;
  • (2)线程A获得了锁1,线程B获得了锁2,这时线程A调用lock试图获得锁2,结果是需要挂起等待线程B释放锁2,而这时线程B也调用lock试图获得锁1,结果是需要挂起等待线程A释放锁1,于是线程A和B都在等待对方释放自己才释放,从而造成两个都永远处于挂起状态,造成死锁。

6.有GLF锁为什么还要有互斥锁

非python环境中,单核情况下,同时只能有一个任务执行。多核时可以支持多个线程同时执行。但是在python中,无论有多少核,同时只能执行一个线程。究其原因,这就是由于GIL的存在导致的。

GIL(全局解释器锁),来源是python设计之初的考虑,为了数据安全所做的决定。某个线程想要执行,必须先拿到GIL,我们可以把GIL看作是“通行证”,并且在一个python进程中,GIL只有一个。拿不到通行证的线程,就不允许进入CPU执行。GIL只在cpython中才有,因为cpython调用的是c语言的原生线程,所以他不能直接操作cpu,只能利用GIL保证同一时间只能有一个线程拿到数据。

十六、python垃圾回收机制

引用计数是一种垃圾收集机制,而且也是一种最直观,最简单的垃圾收集技术。当 Python 的某 个对象的引用计数降为 0 时,说明没有任何引用指向该对象,该对象就成为要被回收的垃圾了。比如 某个新建对象,它被分配给某个引用,对象的引用计数变为 1。如果引用被删除,对象的引用计数为 0, 那么该对象就可以被垃圾回收。不过如果出现循环引用的话,引用计数机制就不再起有效的作用了。
一般是类中的__del__方法进行的。

十七、MongoDB

1.MongoDB和传统的关系型数据库区别

  • 1.传统数据库特点是存储结构化数据,数据以行为单位,每行的数据结构和类型相同
  • 2.MongoDB存储的是文档,每个文档得结构可以不相同,能够更便捷的获取数据。
  • 3.MongoDB的集合不需要提前创建,可隐式创建,而关系型数据库的表需要提前定义
  • 4.mongo第三方支持丰富。(这是与其他的NoSQL相比,MongoDB也具有的优势)
  • 5.mongodb不支持事务操作
  • 6.mongodb支持大容量的存储,占用空间过大

2.MongoDB和sql的对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qeA5AAmA-1575721569808)(../../AppData/Roaming/Typora/typora-user-images/1575705781687.png)]

3.游标

定义:由于mongodb底层是js编写,因此可以使用一些js代码,通俗的说游标不是查询结果,而是查询的返回资源或者接口,就像python中的生成器,通过这个生成器,可以一次一次的获取每一个资源。

十八、scrapy和scrapy-redis

①什么是scrapy

scrapy 是一个快速、高层次的基于 python 的 web 爬虫构架,它用于抓取web站点并从页面中提取结构化的数据。scrapy 使用了 Twisted异步网络库来处理网络通讯。

②Scrapy优缺点

优点:

  • scrapy 是异步的(scrapy 框架的异步机制是基于 twisted 异步网络框架处理的,在 settings.py 文件里可以设置具体的并发量数值(默认是并发量 16))
  • 采取可读性更强的xpath代替正则
  • 强大的统计和log系统
  • 同时在不同的url上爬行
  • 支持shell方式,方便独立调试
  • 写middleware,方便写一些统一的过滤器
  • 通过管道的方式存入数据库

缺点:

  • 基于python的爬虫框架,扩展性比较差
  • 基于twisted框架,运行中的exception是不会干掉reactor,并且异步框架出错后是不会停掉其他任务的,数据出错后难以察觉。

③scrapy的组件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lBdPRM1d-1575721569811)(../../AppData/Roaming/Typora/typora-user-images/1575705944820.png)]

④scrapy和scrapy-redis的区别

  • scrapy是一个Python爬虫框架,爬取效率极高,具有高度定制性,但是不支持分布式。而scrapy-redis一套基于redis数据库、运行在scrapy框架之上的组件,可以让scrapy支持分布式策略,Slaver端共享Master端redis数据库里的item队列、请求队列和请求指纹集合

  • 为什么选择redis数据库,因为redis支持主从同步,而且数据都是缓存在内存中的,所以基于redis的分布式爬虫,对请求和数据的高频读取效率非常高。

    redis的优点

1.数据读取快,因为数据都放在内存上
2.支持事务watch
3.数据持久化,支持快照和日志,方便恢复数据
4.拥有丰富的数据类型:list,string,set,qset,hash
5.支持主从复制,可以进行数据备份
6.丰富的特性:可以作为缓存,消息队列,设置过期时间,到期自动删除

⑤分布式爬虫主要解决什么问题?

ip、带宽、cpu、io

⑥scrapy如何实现分布式抓取?

  • 可以借助scrapy_redis类库来实现。在分布式爬取时,会有master机器和slave机器,其中,master为核心服务器,slave为具体的爬虫服务器。
  • 我们在master服务器上搭建一个redis数据库,并将要抓取的url存放到redis数据库中,所有的slave爬虫服务器在抓取的时候从redis数据库中去链接,由于scrapy_redis自身的队列机制,slave获取的url不会相互冲突,然后抓取的结果最后都存储到数据库中。master的redis数据库中还会将抓取过的url的指纹存储起来,用来去重。相关代码在dupefilter.py文件中的request_seen()方法中可以找到。

⑦定时任务

1.可以设计一个定时的类,使用时间模块(time,datetime),比如爬取时候获取当前时间,再当前时间多久后再爬取

2.使用linux的crontab的计划任务
	crontab -l 列出所有的定时任务    看不到配置文件中写的定时任务  
	crontab -e 新增计划任务  跟上面的区别在于  没有用户名 
	crontab  -r 清空计划任务  
	分  时 日  月  周   命令    
	 	
	举例使用:
	*  *   *   *  *    命令   每分每时每天每月每周 执行这个命令  
	0-59 0-23 1-31 1-12 0-6  0是 周天 1-6 周一到周六      
	0  2   *   *   *   mysqldump  每天的2点备份数据库  
	0  2   *   *   2   sync    每个周二的2点做数据同步     
	0  8   15  *   *   /home/jsgz.py 每个月15号的八点给大家算工资  
	0  */2 *   *   *   /home/camera.py 每隔2个小时执行一次查看摄像头  
	0  8,12,18 * * 1-5 kq.py    每周1-5 的 8点 12点 18点  执行打卡  
	0  8  *  * * *  spider.sh   每天 8点爬虫

十九、 使用过的爬虫框架或者模块有哪些?

  • Python自带:urllib,urllib2,但是没有使用过

    urlliburllib2模块都做与请求URL相关的操作,但他们提供不同的功能。
    urllib2:urllib2.urlopen可以接受一个Request对象或者url,(在接受Request对象时候,并以此可以来设置一个URL 的headers),urllib.urlopen只接收一个url
    urllib 有urlencode,urllib2没有,因此总是urllib,urllib2常会一起使用的原因

  • 第 三 方:requests

    requests 是一个HTTP库, 它只是用来,进行请求,对于HTTP请求,他是一个强大的库,下载,解析全部自己处理,灵活性更高,高并发与分布式部署也非常灵活,对于功能可以更好实现.

  • 框 架:Scrapy

    scrapy是封装起来的框架,他包含了下载器,解析器,日志及异常处理,基于多线程, twisted的方式处理,对于固定单个网站的爬取开发,有优势,但是对于多网站爬取 100个网站,并发及分布式处理方面,不够灵活,不便调整与括展。

二十、MyISAM 与 InnoDB 两个引擎有什么区别?

  • InnoDB 支持事务,MyISAM 不支持,这一点是非常之重要。事务是一种高级的处理方式,如果在一些列增删改中只要哪个出错还可以回滚还原,而 MyISAM就不可以了;
  • MyISAM 适合查询以及插入为主的应用,InnoDB 适合频繁修改以及涉及到安全性较高的应用;
  • InnoDB 支持外键,MyISAM 不支持;
  • MyISAM 是默认引擎,InnoDB 需要指定;
  • InnoDB 不支持 FULLTEXT 类型的索引;
  • InnoDB 中不保存表的行数,如 select count( * ) from table 时,InnoDB;需要扫描一遍整个表来计算有多少行,但是 MyISAM 只要简单的读出保存好的行数即 可。注意的是,当 count( * )语句包含 where 条件时 MyISAM 也需要扫描整个表;
  • 对于自增长的字段,InnoDB 中必须包含只有该字段的索引,但是在 MyISAM表中可以和其他字段一起建立联合索引;
  • 清空整个表时,InnoDB 是一行一行的删除,效率非常慢。MyISAM 则会重建表;

二十一、写爬虫是用多进程好?还是多线程好? 为什么?

  • IO密集型情况使用多线程
  • 计算密集型情况下使用多进程

解释: IO 密集型代码(文件处理、网络爬虫等),多线程能够有效提升效率(单线程下有 IO 操作会进行 IO 等待,造成不必要的时间浪费,而开启多线程能在线程 A 等待时,自动切换到线程 B,可以不浪费 CPU 的资源,从而能提升程序执行效率)。在实际的数据采集过程中,既考虑网速和响应的问题,也需要考虑自身 机器的硬件情况,来设置多进程或多线程。

二十二、数据库的优化?

为什么要优化?

一个应用吞吐量瓶颈往往出现在数据库的处理速度上,随着应用程序的使用和业务的拓展,数据库数据量逐渐增多,数据库处理压力逐渐增大,关系型数据库数据存放在磁盘上的,读写速度较慢(与内存中的数据相比)

优化方式:

  • 设计表的时候严格根据数据库的设计范式来设计数据库;
  • select 后尽量不使用*
  • 尽量不使用嵌套查询,使用连接查询或者where查询
  • sql关键词尽量使用大写
  • 尽量使用逻辑外交不使用物理外键
  • 给查询频繁的字段添加索引,并且遵循最左原则(尽量将首选关键字段放在最前边)
  • 垂直分库分表:把一些不经常读的数据或者结果复杂的表拆分成多张表,较少磁盘I/O操作;
  • 水平分库分表:于数据量庞大的表,使用水平分库分表
  • 使用缓存,把经常访问到的数据而且不需要经常变化的数据放在缓存中,能节约磁盘IO;
  • 优化硬件;
  • 主从分离读写;采用主从复制把数据库的读操作和写入操作分离开来;

二十二、使用过的解析数据包

Xpath、正则

二十三、怎么监控爬虫的状态

(1)使用 python 的 STMP 包将爬虫的状态信心发送到指定的邮箱

(2)钉钉机器人或者企业微信机器人

(3)引入日志

二十四、TCP和UDP协议的区别

  • tcp的目的是提供可靠的数据传输,并在相互进行通信的设备或服务之间保持一个虚拟连接,tcp在数据包接收无序,丢失或在交付期间被破坏时,负责数据的恢复,tcp面向连接,如打电话要先拨号建立连接,udp则是无连接的,即发送数据之前不需要建立连接。
  • tcp提供可靠的服务,通过tcp连接传送的数据能无差错,不丢失、不重复、且按序到达,而udp是尽最大努力交付,但不保证可靠交付,每一条tcp连接只能是点到点的,而udp支持一对一,一对多,多对一和多对多的交互通信。

二十五、Nginx的正向代理和反向代理

web 开发中,部署方式大致类似。简单来说,使用 Nginx 主要是为了实现分流、转发、负载均衡, 以及分担服务器的压力。Nginx 部署简单,内存消耗少,成本低。Nginx 既可以做正向代理,也可以做反向代理。

  • 正向代理:请求经过代理服务器从局域网发出,然后到达互联网上的服务器。特点:服务端并不知道真正的客户端是谁。
  • 反向代理:请求从互联网发出,先进入代理服务器,再转发给局域网内的服务器。特点:客户端并不知道真正的服务端是谁。

区别:正向代理的对象是客户端。反向代理的对象是服务端。

二十六、缓存穿透、缓存雪崩

redis技术就是NoSQL技术中的一种,但是引入redis又有可能出现缓存穿透,缓存击穿,缓存雪崩等问题。

1.缓存穿透:

  • 产生原因: 缓存穿透又称缓存击穿,是指在高并发场景下缓存中(包括本地缓存和redis缓存)的某一个key被高并发的访问并没有命中, 此时会去db中访问数据,导致数据库并发的执行大量查询操作,对db造成巨大压力。
  • 解决方案一:
    对缓存失效的key加分布式锁,当一个key在本地缓存以及redis缓存中未查询到数据,此时对key加分布式锁访问db ,如果取到数据反写到缓存中,避免大量请求进入db ;如果取不到数据则缓存一个空对象 ,这样可以保证db不会被大量请求直接打挂,从而引起缓存颠簸,更甚者缓存雪崩效应。
  • 解决方案二:
    在本地缓存一个set集合,存储对应数据为空的key的集合,在请求前做拦截,此种方式牵涉到数据变更还要校验set集合的问题,一般适用于数据更新较少的场景
  • 解决方案三:
    使用布隆过滤器

2.缓存雪崩:

  • 产生原因: 当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。

  • 解决方案一:
    ①缓存失效时的雪崩效应对底层系统的冲击非常可怕!大多数系统设计者考虑用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。

  • 解决方案二:
    简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

二十七、Redis的持久化机制

①持久化:日志和快照对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ieNhS7iD-1575721569809)(../../AppData/Roaming/Typora/typora-user-images/1575705877736.png)]

②快照和日志两者如何选择?

推荐两种共同使用

  • 1.如果redis仅仅是用来做为缓存服务器的话,我们可以不使用任何的持久化。
  • 2.一般情况下我们会将两种持久化的方式都开启。redis优先加载AOF文件来回复数据。RDB的好处是快速。
  • 3.在主从节点中,RDB作为我们的备份数据,只在salve(从节点)上启动,同步时间可以设置的长一点,只留(save 900 1)这条规则就可以了。
  • 4.开启AOF的情况下,主从同步是时候必然会带来IO的性能影响,此时我们可以调大auto-aof-rewrite-min-size的值,比如5GB。来减少IO的频率
  • 5.不开启AOF的情况下,可以节省IO的性能影响,这是主从间通过RDB持久化同步,但如果主从都挂掉,影响较大

③在dump rdb过程中,aof如果停止同步,会不会丢失?

答: 不会,所有的操作缓存在内存的队列里, dump完成后,统一操作.

④aof重写是指什么?

答:由于日志保存的是所有操作命令,导致存的日志会过大,而且数据库中有可能数据进行过删除,因此日志中的一些命令就相当于无效,因此日志先会删除,然后内存中的数据会逆化成命令,再重新写入到日志文件中,以解决 aof日志过大的问。

⑤如果rdb文件,和aof文件都存在,优先用谁来恢复数据?

答: 在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件完整。

⑥恢复时rdb和aof哪个恢复的快?

答: rdb快,因为其是数据的内存映射,直接载入到内存,而aof是命令,需要逐条执行

猜你喜欢

转载自blog.csdn.net/qq_40558166/article/details/103044923