面试总结
第一天
一句话翻转字典的key和value python的自省机制 元祖和列表的区别 tcp和udp优缺点
tcp和udp差别 GIL全局解释器锁 cookies selenium怎么解析数据 为什么用selenium
一句话翻转字典的key和value
方法一:列表生成式 dict([(v,k) for k,v in dict1.items()])
方法二:生成器 dict((v,k) for k,v in dict1.items())
python的自省机制
help() 查看对象的帮助文档
dir() 查看对象有什么方法属性,即对象有什么用
元祖和列表的区别
首先他们都是一个容器,可以包含一系列对象(有序) 而字典和集合是无序的
技术上的区别:元祖是不可变的 ,即元祖不能修改
扩展:字典的key必须是不可变的,因为key要进行hash 只有不可变类型才能进行hash
tcp和udp优缺点:
tcp优点:可靠(在数据传送之前,会进行三次握手建立连接,传输过程有确认、窗口、重传、 数据传送完成后,也会断开连接用来节省资源 ),稳定 缺点; 慢 效率低 占用资源高,容易被攻击,在连接和中间传输(确认机制、重传机制,拥塞机制都会消耗大量时间)过程都会消耗时间。
ud优点:快,比tcp稍微更安全,没有tcp的三次握手,确认、重传、拥塞(没有这些机制被攻击者利用的漏洞就少一些,但是也不可避免被攻击,如flood攻击),因为是无状态的传输协议,所以在传输数据时比较快 缺点:不可靠,不稳定(因为没有那些可靠的机制,在网络不好的时候就会出现丢数据)
当对数据要求完整就选择用tcp (如http https 浏览器)
当对网络质量要求不高,要求传输速度快的时候有udp (qq语音 视频)
tcp和udp差别: tcp udp
1:基于连接于不连接 是否连接 连接 不连接
2;对系统资源要求(tcp要求资源多) 传输可靠性 可靠 不可靠
3:udp的程序结构简单 应用场合 传输大量数据 少量数据
4:流模式与数据报模式 速度 慢 快
5:tcp保证数据顺序准确性,udp网络不好可能对数据,
GIL全局解释器锁:
四核机器开四个线程,四个cpu也不会全占用,因为python里边有GIL锁
python语言和GIL锁没有半毛钱关系,只是由于历史原因在Cpython里难以移除GIL
每个线程在执行都要先获取GIL,保证同一时刻置于一个线程在执行代码
在爬虫中多线程是比单线程性能有提升的,因为遇到IO堵塞会自动释放GIL
python中多进程是可以利用多核cpu的
并发:交替执行任务
并行:同时执行多个任务
解决GIL问题:
1:更换解释器jpython
2::使用多进程完成多任务
cookies:
网站为了辨别用户身份、进行会话跟踪,存储在用户本地的纯文本(通常会加密)
cookie是由服务器生成,发送给浏览器,游览器保存key value 再次请求直接带上游览器保存的key value
cookie基于域名安全,不同域名cookie是不能访问的
游览器的同源策略
应用:
最典型的应用是判定注册用户是否已经登录网站,用户可能会得到提示,是否在下一次进入此网站时保留用户信息以便简化登录手续,这些都是Cookie的功用。
网站的广告推送,经常遇购物车,用户可能会在一段时间内在同一家网站的不同页面中选择不同的商品,这些信息都会写入Cookie,以便在最后付款时提取信息到访问某个网站时,会弹出小窗口,展示我们曾经在购物网站上看过的商品信息。
cookie在response设置(可以设置有效期,在响应头可以查看) 在request取(加八个小时东八区,1970-1-1)
删除cookie只是把cookie的到期时间设置的和创建时间相同
selenium怎么解析数据
只是把特定的ur进行动态加载(url要经过判断筛选)
在下载器中间键里使用selenium,用selenium得到响应体,自己构建响应对象,然后把响应对象给引擎,不用去下载器进行交互
class SeleniumMiddleware(object):
def process_request(self, request, spider):
# 过滤需要动态加载的url
url = request.url
if 'daydata' in url:
driver = webdriver.Chrome()
driver.get(url)
time.sleep(3)
data = driver.page_source
driver.close()
# 构建响应,并将响应返回
res = HtmlResponse(
url=url,
request=request,
encoding='utf-8',
body=data
)
return res
为什么用selenium:
有的数据在源码上找不到(js加密加载,ajax请求参数加密),它是通过运算出来的,这是用selenium更方便一些
scrapy 和 scrapy-redis区别
scrapy中多个spider不能共享任务队列,每个spider占用一个进程
scrapy-redis :多台机器协同完成一项任务,从而缩短执行任务时间
优点:1单节点不稳点不影响整体任务执行 2提升整体运行效率 3可以实现断点续爬功能
区别:起始请求放在了redis里,然后slaver端的spider随机抢起始url,谁抢到谁构建请求对象,然后给引擎,引擎交给scheduler,scheduler进行hash(必须是字符串对象),再交给redis里的重复过滤器,再到任务队列,然后slaver端(scheduler拿)又随机抢request对象,在给引擎,引擎经过下载器中间键给下载器,与互联网交互得到响应对象,经过中间键,引擎给spider,解析出数据和url(对其进行构建成请求对象),经过引擎,数据给item,请求对象给scheduler,再给重复过滤器,,经过过滤,再给任务队列,然后slaver端再随机抢请求对象,如此循环,知道任务队列没有任务,程序就会结束
遇到哪些反扒
1:基于请求头的反扒,比如服务器根据ua(用户代理)告诉服务器我是一个怎么样的游览器,根据ua可以判断出客户端游览器类型,cpu类型,操作系统版本,根据refer告诉服务器我从哪里来,从哪个页面跳转过来,还可以应用在防盗链
2:基于用户行为的反扒 同一ip短时间内大量访问(可以用ip代理解决) 同一账户短时间进行大量相同操作(用delay延迟解决,有的还可以退出之后再登陆解决)
3:动态加载 一些ajax(请求参数加密) 请求 js加载很难获取源码上的数据
状态码:
200 请求成功 302 重定向 401 请求已经收到 正在处理 403 访问被禁止(被识别出是爬虫) 404 url 有问题 500 服务器内部问题(有的服务器识别出爬虫就会发送500状态码) 503 服务器不能处理当前请求,过一段时间可能进行处理
http工作原理
HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据
1、客户端连接到Web服务器
使用tcp协议产生套接字连接
2、发送HTTP请求
建立套接字连接后,发送请求报文(包括url 请求行,请求头,空行 ,请求数据)
3、服务器接受请求并返回HTTP响应
服务器接受请求,解析请求,定位请求资源,把资源(状态行,响应头,空行,响应数据)放在套接字里边传送
4、释放连接TCP连接
若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求
5、客户端浏览器解析HTML内容
头条的反扒机制
类对象 实例对象
累属性和实例属性区别就是两者的归属不同,类属性只在内存中存一份,实例属性在每个对象中都要存储
类方法实例方法、静态方法,三种方法在内存中都归属于类,在内存中只保存一份,区别在于调用方式不同
实例方法:由实例对象调用;至少一个self参数;执行实例方法时,自动将调用该方法的对象赋值给self;
类方法:由类和实例对象都可以调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类赋值给cls;
静态方法:由对象调用;无默认参数
第二天
怎么读取特别大的文件:
1 通过生成器,多次读取,每次读取少量文件(500m),经过处理后再读取下一个500m文件
2用linux的split方法按行或按文件大小把超大大文件切割成比较小的可以处理的文件在处理
ssl怎么加密
在http和tcp之间有一个ssl层,从发送端看,负责把http传过来的消息加密给tcp,从接收端看,负责把加密的信息解密 http---->ssl------->tcp-------->iP
常用的加密算法:
对称加密算法:加密和解密采用相同的秘钥,有RC5,RC4(序列加密) ,IDEA(分组加密),DES
非对称加密算法:加密和解密的过程是不同的,加密使用公开的公钥,解密使用私有的私钥。比如A接受,B发送,B会形成一对公私钥,把公钥给A ,然后根据这个公钥A进行加密,加密后的信息给B,B根据这个公钥用对应的私钥进行解密,典型的算法有RSA DAS DH
散列算法:把文件通过某种公开的算法变成固定长度的散文(秘钥可有可无),这种散列变化是不可逆的,就是说 不能从散文到原文,因此散列算法可以用于验证原文是否被篡改 有MD5 SHA Base64 CRC
七个协议
物理层(解决两台电脑之间的bytes通过电缆类型传送)----》链接层(解决数据通过无线电之间的传送)-----》传输层(解决发送大量任务,把大量任务打包,并且有错误处理机制,已经到了tcp udp)-----》网络层(解决多台电脑情况下可以找到对应电脑进行传输 产生了ip)------》会化层(实提高用户体验,实现自动收发包,自动寻找对方ip)------->表示层(可以实现自动传包和找ip 但是不同系统电脑之间沟通有语法障碍,所以就有了会话层)------------》应用层(可以写各种运行的软件等,http就在应用层)
三次握手 四次挥手(tcp)
三次握手:client发送一个连接标志位syn=1和连接报文seq=k(随机生成,来给这次连接加上一个特定的变好而已)告诉服务端我要连接,服务端确认后返回ysn=1,ACK=1(告诉客户端服务端已经准备好),ack=k+1(标志是这次连接),seq=j (连接报文,标志唯一连接序号) 客户端收到之后,发送ack=j+1,ACK=1,告知服务端客户端也准备好了,可以发送,三次握手就是确认双方双方收发功能正常
四次挥手:client发送一个断开连接标志位fin和断开连接报文m(随机值)告知服务端我要断开连接,服务端收到消息后发送一个ACK(告知client我已经收到消息)和确认报文m+1,告诉client我已经收到请求,但是client得再等一会,我这边任务还没有处理完,等处理完成后,发送一个fin和n,告诉client我已经执行完成close,客户端收到消息后返回一个ACK确认和n+1报文,告知服务端我这边已经关闭完毕
两种获取ip代理方式:
一种是自建代理池,每次请求都要去代理池获取一个ip,然后返回给爬虫文件,然后用该ip代理服务器发送请求后的响应
另一种是用ip代理隧道,使用ip代理隧道,省去获取ip这一程序,在ip代理隧道随机选择一个ip ,然后通过该ip服务器请求网页
结构化数据和非结构化数据爬取
结构化数据:json xml 在数据交互用的很多,比如web前后端数据传送
非化数据:html 文本 用xpath路径提取方式提取结构
经常用到哪些模块
requests time os sys hashlib random re logging datetime
邮箱正则表达式:
[0-9a-zA-Z_-]+@[0-9a-zA-Z_-]+(.[0-9a-zA-Z_-]+)$
爬取淘宝遇到过哪些反扒手段
爬虫异步任务问题解决
redis为什么关机还会保留缓存
set求交集
scrapy 爬取过程中ip被封怎么办
自定义异常
多线程实现爬虫逻辑
分别使用队列保存 url队列 响应队列 数据队列 然后可以在获取相应和解析数据的时候多开几个线程 保存数据可以少开点线程,防止数据队列为空出现异常,因为在获取响应和解析数据时是设置死循环,所以不能让主线程等待子线程,要让主线程等待队列退出而退出,这里当队列完成任务,就要宣告一下,不会出现一直等待
进程之间怎么通讯
进程之间怎么设置锁
selenium怎么实现高并发
进程之间怎么解决资源竞争
日志怎么写入文件
在用scrapy时候,在setting里自己写LOG_FILE = ‘文件名’ 日志就会写入这个文件
LOG_LEVEL = ‘INFO’ 在工作中一般会设置info等级
项目怎么部署
数据库怎么实现并发
第三方裤验证码逻辑怎么实现的 需要截图吗
定时爬取关 有个第三方库
查看进程IP的Linux语法
多线程情况下怎么解决往mysql数据库写入重复数据
有三种数据库锁
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
适用:从锁的角度来说,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用;而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统