爬虫面试python

233 阅读13分钟

1. 什么是爬虫

  • 网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。

2. 什么是URL

  • URL,即统一资源定位符,也就是我们说的网址,统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的 URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。

3. Scrapy的优缺点

  • 优点:scrapy 是异步的, 对于固定单个网站的爬取开发,有优势
  • 缺点:基于 python 的爬虫框架,扩展性比较差,不够灵活.

4. HTTP和HTTPS的区别

  • http免费, https 协议需要到 ca 申请证书,一般免费证书很少,需要交费;
  • http 是超文本传输协议,信息是明文传输,https 则是具有安全性的 ssl 加密传输协议;
  • http 和 https 使用的是完全不同的连接方式用的端口也不一样,前者是 80,后者是 443;
  • http的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

5.HTTPS如何进行数据传输

  • HTTPS 其实就是在 HTTP 跟 TCP 中间加多了一层加密层 TLS/SSL。SSL 是个加密套件,负责对 HTTP 的数据进行加密。TLS 是 SSL 的升级版。现在提到 HTTPS,加密套件基本指的是 TLS。原先是应用层将数据直接给到 TCP (是一种面向连接的、可靠的、基于字节流的传输层通信协议)进行传输,现在改成应用层将数据给到TLS/SSL,将数据加密后,再给到 TCP 进行传输。

6. get和post请求的区别

get请求和post请求都是TCP链接,本质上并无区别, 但是由于HTTP的规定和浏览器/服务器的限制导致他们在应用过程中体现有所不同:

  • get请求能够被缓存,post不能
  • get请求会被保存到浏览器的浏览记录里,post不能
  • get请求的url可以保存为书签,post不能
  • get请求有长度限制,post没有
  • get产生一个TCP数据包(把http header和data一并发送出去,服务器响应200(返回数据));post产生两个TCP数据包(浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据))。

7. Scrapy框架的运行机制

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

  • spider将想要爬取的url的request对象传递给engine
  • engine将request对象传递给scheduler,按某种算法进行排队
  • 之后的某个时刻将处理好的request对象传递给engine
  • engine将request对象传递给downloader
  • Downloader根据middleware中的规则,使用request对象中的url地址发出HTTP请求到网站服务器,将服务器返回的响应构造一个response对象,包含页面的html文本,并将response对象返回给engine
  • engine将response对象传递给spider进行数据提取
  • 若提取出item,则由engine传递给itempipeline进行数据保存
  • 若提取出url,则由engine传递给scheduler等待新一轮的数据抓取.

8. 什么是scrapy_Redis分布式爬虫

  • scrapy 是一个 Python 爬虫框架,爬取效率极高,具有高度定制性,但是不支持分布式。而 scrapy-redis 是一套基于 redis 数据库、运行在 scrapy 框架之上的组件,可以让scrapy 支持分布式策略,Slaver 端共享 Master 端 redis 数据库里的 item 队列、请求队列和请求指纹集合。为什么选择 redis 数据库,因为 redis 支持主从同步,而且数据都是缓存在内存中的,所以基于 redis 的分布式爬虫,对请求和数据的高频读取效率非常高.

9. 实现模拟登录的方式有哪些

  • 使用一个具有登录信息的cookie,结合请求报头直接进行get请求,访问登录后才能访问的页面;
  • 先发送登录界面的get请求,在登录页面html里获取登录所需的参数,结合账号密码,进行post请求,若参数进行了加密,则需要解密.

10. scrapy的优点

  • 更容易构建大规模的爬取项目
  • 异步处理请求,速度快
  • 可以使用自动调节机制自动调整抓取速度
  • 提供了一个爬虫任务管理界面, 可以实现爬虫的启动、调试和停止,支持定时爬取任务
  • 代码简洁,功能强大

11. Scrapy的指纹去重

  • 对于每一个URL请求,scheduler会根据请求的相关信息加密得到一个指纹信息, 并且与set()集合里面的指纹信息进行对比, 如果集合中存在这个指纹信息, 那么不会将该request放入队列.

12. 关系型数据库和非关系型数据库区别?

  • 关系型(表格式):MySQL、Postgresql、Oracle、DB2、SQL Server

  • 非关系型:Mongodb(文档型)、Redis(键值对型)、Hbase(列存储)

  • 1、存储方式不同

    • 关系型数据天然就是表格式的,因此存储在数据表的行和列中。
    • 非关系型数据通常存储在数据集中,就像文档、键值对或者图结构。
  • 2、扩展方式不同

    • 关系型数据库是纵向扩展,也就是说提高处理能力,使用速度更快速的计算机,这样处理相同的数据集就更快了。
    • 非关系型数据库是横向扩展,天然就是分布式的,可以通过给资源池添加更多普通的数据库服务器(节点)来分担负载。
  • 3、对事务性的支持不同

    • 性能和稳定性关系型优于非关系型

13. 怎么选择数据的存储方式

  • Redis基于内存,通过 Key-Value 键值对的的方式存储数据,读写速度快,也可做持久化,但是内存空间有限,当数据量超过内存空间时,需扩充内存,但内存价格贵;
  • MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它是一个内存数据库,数据都是放在内存里面的。
  • MySQL基于磁盘,读写速度没有Redis快,但是不受空间容量限制,性价比高;

14. python2和python3的区别

  • 字符串类型、默认字符、print方法、除法的数字类型、导入方式、继承类、元类声明、异常处理、字典、模块合并、部分模块重命名

    • Python2 既可以使用带小括号的方式,也可以使用一个空格来分隔打印内容,比如 print ‘hi’

      Python3 使用 print 必须要以小括号包括打印内容,比如 print(‘hi’)

    • python2 range(1,10)返回列表,python3中返回迭代器,节约内存

    • python2中使用ascii编码,python3中使用utf-8编码

    • python2中unicode表示字符串序列,str表示字节序列

      python3中str表示字符串序列,byte表示字节序列

    • python2中为正常显示中文,引入coding声明,python3中不需要

    • python2中是raw_input()函数,python3中是input()函数

15. 生成器、迭代器、装饰器

  • 生成器

    • Python的生成器是一个返回可以迭代对象的函数。容易使用,代码量较小,内存使用更加高效。仅仅在需要的时候才使用。
  • 迭代器

    • 可以直接作用于for循环的数据类型有以下几种:

      • 一类是集合数据类型,如list,tuple,dict,set,str等
      • 一类是generator ,包括生成器和带yeild的generator function

    这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

    可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

  • 装饰器

    • 在函数调用前后自动打印日志,又不改变原函数,在代码运行期间动态增加功能的方式称之为“装饰器”。

    • 装饰器的语法以@开头,接下来是装饰器函数的名字和可选的参数,紧跟着装饰器声明的是被修饰的函数和装饰函数的可选参数。

    • 3大特征:

      • 外部函数包含内部函数;
      • 返回一个内部函数;
      • 内部函数用到外部函数的变量。

16. 多线程和多进程

  • 进程:

    • 一个程序在操作系统中被执行以后就会创建一个进程,通过进程分配资源(cpu、内存、I/O设备)
  • 线程:

    • 线程从属于进程,是程序的实际执行者,在一个进程执行的过程,一般会分成很多个小的执行单位,线程就是这些执行单位;线程占用的是cpu。
  • 一个程序至少拥有一个进程,一个进程至少拥有一个线程。进程负责资源的调度和分配,线程才是程序真正的执行单元,负责代码的执行。

  • 由于全局解释锁(GIL)的存在,同一时间点只有一个线程被执行,所以python多线程并不是并行执行,因此较适合于I/O密集型程序,多进程并行执行适用于CPU密集型程序:

    • CPU密集型:程序需要占用CPU进行大量的运算和数据处理;
    • I/O密集型:程序中需要频繁的进行I/O操作;例如网络中socket数据传输和读取等;

17. 协程

  • 协程(Coroutines)是一种比线程更加轻量级的存在,是一种特殊的函数,正如一个进程可以拥有多个线程一样,一个线程可以拥有多个协程。但是一个线程的多个协程的运行是串行的,当一个协程运行时,其它协程必须挂起。

    • 高并发+高扩展性+低成本
    • 跨平台、跨体系架构
    • 无需线程上下文切换的开销

18. 如何提升Scrapy的爬取效率

  • 增加并发

    • 默认scrapy开启的并发线程为32个, 可以适当进行增加. 在settings配置文件中修改`CONCURRENT_REQUESTS = 100值为100, 并发设置成了为100.
  • 降低日志级别

    • 在运行scrapy时, 会有大量日志信息的输出, 为了减少CPU的使用率. 可以设置log输出信息为INFO或者ERROR. 在配置文件中编写: LOG_LEVEL = ‘INFO’
  • 禁止cookie

    • 如果不是真的需要cookie, 则在scrapy爬取数据时可以禁止cookie从而减少CPU的使用率, 提升爬取效率. 在配置文件中编写: COOKIES_ENABLED = False.
  • 禁止重试

    • 对失败的HTTP进行重新请求(重试)会减慢爬取速度, 因此可以禁止重试. 在配置文件中编写: RETRY_ENABLED = False
  • 减少下载超时

    • 如果对一个非常慢的链接进行爬取, 减少下载超时可以能让卡住的链接快速被放弃, 从而提升效率. 在配置文件中进行编写: DOWNLOAD_TIMEOUT = 10 超时时间为10s.

19. 一次完整的网络请求

  • 域名解析;
  • TCP的三次握手;
  • 建立TCP连接后发起HTTP请求;
  • 服务器响应HTTP请求;
  • 浏览器解析html代码,同时请求html代码中的资源(如js、css、图片);
  • 最后浏览器对页面进行渲染并呈现给用户。

20. TCP的三次握手和四次挥手

  • 三次握手

    • 第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
    • 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
    • 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
  • 四次挥手

    • 客户端发出关闭连接报文,并停止传输数据;
    • 服务器收到关闭连接报文,发出确认报文;
    • 服务器最后的数据发送完毕后,发出关闭连接报文;
    • 客户端收到报文,发出确认,在2MSL(最长报文段寿命)后进入CLOSED状态,服务器收到确认后立即进入CLOSED状态,完成四次挥手;

21. 常见的反爬,怎么解决

  • 通过headers反爬:添加headers,例如user-agent和cookie
  • 基于用户行为反爬:添加IP代理池或降低爬取频率
  • 验证码:移交打码平台处理
  • 数据加密:js逆向
  • 基于动态页面的反爬:selenium

22. __new__和__init__的区别

  • __new__在创建对象时调用,返回当前对象的一个实例
  • __init__在创建对象后调用,无返回值

23. 对字典排序

alist=[{"name":"a", "age":20}, {"name":"b", "age":30}, {"name":"c", "age":25}]
sorted(alist,key=lambda keys:keys['age'])

24. request中包含什么

  • 请求方式:get和post
  • 请求url
  • 请求头:User-Agent(浏览器请求头)、Host、Cookies信息
  • 请求体:GET请求时,一般不会有,POST请求时,请求体一般包含form-data

25. response中包含什么

  • 响应状态:状态码 正常响应200
  • 响应头:如内容类型、内容长度、服务器信息、设置cookie等
  • 响应体信息:响应源代码、图片二进制数据等等

26. 常见的http响应状态码

  • 200: 服务器请求正常
  • 301:被请求的资源已永久移动到新位置。服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
  • 302:请求的资源临时从不同的URI响应请求,但请求者应继续使用原有位置来进行以后的请求
  • 401:请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
  • 403:服务器已经理解请求,但是拒绝执行它。
  • 404:请求失败,请求所希望得到的资源未被在服务器上发现。
  • 500:服务器遇到了一个未曾预料的状况,导致无法完成对请求的处理。一般来说,这个问题都会在服务器的程序码出错时出现。
  • 503:由于临时的服务器维护或者过载,服务器当前无法处理请求。