python爬虫面试题

python是如何进行内存管理的?

a、对象的引用计数机制

python内部使用引用计数,来保持追踪内存中的对象,Python内部记录了对象有多少个引用,即引用计数,当对象被创建时就创建了一个引用计数,当对象不再需要时,这个对象的引用计数为0时,它被垃圾回收。

b、垃圾回收

例如当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。

c、内存池机制

Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。

写一个Python中的单例模式

class Singleton(object):

  _instance = None

  def __new__(cls, *args, **kw):

  if not cls._instance:

    cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)

  return cls._instance

class MyClass(Singleton):

  a = 1

one = MyClass()

two = MyClass()

id(one) = id(two)

爬虫框架scrapy的工作流程?

首先Spiders(爬虫)将需要发送请求的url(requests)到Engine(引擎)。

Engine(引擎)把request交给Scheduler(调度器)。

Scheduler经过排序,入队处理后,重新把request发送到Engine。

Engine把request请求通过DownloaderMiddlewares(可选,主要有User_Agent, Proxy代理)交给Downloader(下载器)。

Downloader向网站发送请求,并接受下载响应(Response),将Response返回给Engine。

Response由Engine,经过SpiderMiddlewares(可选)发送到Spiders开始解析。

解析数据完成后,将所需的Items原路返回到Engine。

Engine将Items发送到ItemPipeline(可以是本地,可以是数据库),提取下一个url再次进行循环。

scrapy的去重原理 (指纹去重到底是什么原理)

对于每一个url的请求,调度器都会根据请求得相关信息加密得到一个指纹信息,并且将指纹信息和set()集合中的指纹信息进行比对,如果set()集合中已经存在这个数据,就不在将这个Request放入队列中。如果set()集合中没有存在这个加密后的数据,就将这个Request对象放入队列中,等待被调度。

请简要说明视图的作用

隐藏数据复杂性;有利于用户对于数据库中某些列数据的访问;使用户查询变得简单;

scrapy中间件有几种类,你用过那些中间件

scrapy中间件理论上有三种(Schduler Middleware,Spider Middleware,Downloader Middleware),在应用上一般有以下两种Spider Middlewares(主要功能是在爬虫运行过程中进行一些处理.) 和 Downloader Middlewares(主要功能在请求到网页后,页面被下载时进行一些处理.)两种。将fake-useragent和IP代理集成到Middlewares中,使Spider在发送request时主动更换User-Agent和IP。

分布式原理

分布式爬虫主要由主机与从机,我们把自己的核心服务器(主机)称为 master,而把用于跑爬虫程序的机器(从机)称为 slave。

我们首先给爬虫一些start_urls,spider 最先访问 start_urls 里面的 url,再根据我们的 parse 函数,对里面的元素、或者是其他的二级、三级页面进行抓取。而要实现分布式,只需要在这个starts_urls里面做文章就行了。进一步描述如下:

1.master 产生 starts_urls,url 会被封装成 request 放到 redis 中的 spider:requests,总的 scheduler 会从这里分配 request,当这里的 request 分配完后,会继续分配 start_urls 里的 url。

2.slave 从 master 的 redis 中取出待抓取的 request,下载完网页之后就把网页的内容发送回 master 的 redis,key 是 spider:items。scrapy 可以通过 settings 来让 spider 爬取结束之后不自动关闭,而是不断的去询问队列里有没有新的 url,如果有新的 url,那么继续获取 url 并进行爬取,所以这一过程将不断循环。

3.master 里的 reids 还有一个 key 是 “spider:dupefilter” 用来存储抓取过的 url 的 fingerprint(使用哈希函数将url运算后的结果),防止重复抓取,只要 redis 不清空,就可以进行断点续爬。

分布式去重原理(布隆过滤的原理)

可以用布隆过滤器(Bloom filiter)进行去重。

from bloomfilter import Bloomfilter

if os.path.exists("命名.data"):

bloom = Bloomfilter("命名.data")

else:

bloom = Bloomfilter(500000)

self.bloom = bloom

.......

self.bloom.add(values)

self.bloom.save("命名.data")

布隆过滤器是一种多哈希函数映射的快速查找算法。它可以判断出某个元素肯定不在集合里或者可能在集合里,即它不会漏报,但可能会误报。对布隆过滤器的一次查询要么返回“可能在集合中“,要么”肯定不在集合里“。通常应用在一些需要快速判断某个元素是否属于集合,但不严格要求100%正确的场合。

关系型数据库和非关系型数据库的区别

关系型数据库优点:1、易于维护:都是使用表结构,格式一致;2、使用方便:SQL语言通用,可用于复杂查询;3、复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。

关系型数据库缺点:1、读写性能比较差,尤其是海量数据的高效率读写;2、固定的表结构,灵活度稍欠;

非关系型数据库优点:1、格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等;2、速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;3、高扩展性;

非关系型数据库缺点:1、不提供sql支持;2、数据结构相对复杂,复杂查询方面稍欠。

什么是匿名函数?有什么优点?

用lambda关键词能创建小型匿名函数。这种函数省略了用def声明函数的标准步骤。

优点:让代码更加精简。不需要考虑命名的问题。代码更容易理解

递归函数

递归:自己调用自己, 肯定还会有一个结束条件

应用场景:重复执行某些相同操作的时候,类似于循环

常用操作:递归求和,递归求阶乘,汉诺塔游戏....

什么是递归?有什么注意事项?怎么解决?

1) 说白了就是自己调自己,但是一般会包含一个结束条件

2) 递归深度超过一定范围会报错,我印象中是998,报堆栈溢出错误,可以通过尾递归进行优化

3) python中没有现成的尾递归,有人封装成"装饰器"来实现

进程和线程的区别

进程:每开启一个应用、项目,会开启至少一个进程,相对来说,进程越多,执行速度越快。但进程越多,系统资源占用越多

线程:每个进程至少一个线程,这个线程称为主线程,其它线程成为子线程。

multiprocessing 多进程 multithreading 多线程

1.同一进程中的线程共享同一内存空间,但是进程之间是独立的。

2.同一进程中的所有线程的数据是共享的,进程之间的数据是独立的。

3.对主线程的修改可能影响其他线程的行为,但是父进程的修改不会影响其他子进程。

4.线程是一个上下文的执行命令,而进程则是与运算相关的一簇资源。

5.同一个进程的线程之间可以直接通信,但是进程之间的交流需要借助中间代理来实现。

6.创建新的线程很容易,但是创建新的进程需要对父进程做一次复制。

7.一个线程可以操作同一个进程的其他线程,但是进程只能操作其子进程。

什么是GIL?

Python没有多线程,因为python中有个GIL(全局解释器锁)每个线程在执行任务的时候会先锁上,做完以后再解锁

什么是闭包?

1. 函数中套函数

2. 内部函数必须使用外部函数中的变量

3. 外部函数必须使用内部函数的返回值

get和post请求的区别

1. 位置不同

get请求的参数放url后

post请求的参数放请求体中

2. 参数长度不同

get请求参数长度有限制,取决于浏览器,貌似1024kb

post请求参数长度理论上无限制,实际取决于浏览器处理能力

3. 安全性不同

post相对get安全一些,但是两者都不安全

4. 以上说法都是一些结论,实际上http协议中并没有规定上述内容

网络七层协议

物 -> 数 -> 网 -> 传 -> 会 -> 表 -> 应

物理层-数据链路层-网络层-传输层-会话层-表示层-应用层

什么叫Socket

1) 是套接字

套接字:应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。

2) 是网络编程的抽象概念

3) 是应用层与TCP/IP协议族通信的中间软件抽象层

4) 是一组接口

5) socket = IP + PORT

socket实现网络通信的两种方式

使用TCP或者UDP来实现 TCP:传输控制协议 UDP:用户数据协议

TCP和UDP的区别?

tcp是可靠的、面向连接的、尽力传输的协议

udp是不可靠的、面向非连接的、不尽力传输的协议。 udp有自己的应用场景,语音和视频几乎都在使用udp协议,它的不可靠只是相对于 tcp来说的,但是它的好处就是效率,高效在某些场景要比可靠性重要。

TCP三次握手过程:

  1 主机A通过向主机B 发送一个含有同步序列号的标志位的数据段给主机B ,向主机B 请求建立连接,通过这个数据段,主机A告诉主机B 两件事:我想要和你通信;你可以用哪个序列号作为起始数据段来回应我.

  2 主机B 收到主机A的请求后,用一个带有确认应答(ACK)和同步序列号(SYN)标志位的数据段响应主机A,也告诉主机A两件事:我已经收到你的请求了,你可以传输数据了;你要用哪佧序列号作为起始数据段来回应我

  3 主机A收到这个数据段后,再发送一个确认应答,确认已收到主机B 的数据段:"我已收到回复,我现在要开始传输实际数据了这样3次握手就完成了,主机A和主机B 就可以传输数据了.

TCP三次握手的特点:

  没有应用层的数据

  SYN这个标志位只有在TCP建产连接时才会被置1

  握手完成后SYN标志位被置0

Django

django-admin startproject MyDjango 通过命令创建django项目

django-admin startapp main 通过terminal创建app来写对应的逻辑

python manage.py makemigrations

python manage.py migrate

通过terminal让Django自动生成数据库的表

python manage.py createsuperuser

通过命令给后台创建超级管理员

django和flask框架之间的差别

1. flask轻量级 django重量级

2. flask自带功能少,django自带功能多

3. django比flask多一个完善的后台

4. flask使用的模板引擎是:Jinja2 Django使用的模板引擎:Django

javascript 知识点

Javascript是一门跨平台、面向对象的轻量级脚本语言。

JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言

JavaScript组成部分:核心 文档对象模型(DOM) 浏览器对象模型

DOM(document object model)是文档对象模型,用来获取或者设置文档中的标签的属性.

JavaScript特点:是解释型脚本语言、向HTML添加交互行为、写成单独的js文件有利于结构和行为的分离、跨平台

你可能感兴趣的:(python爬虫面试题)