1、一、 python语法31. 请说一下你对迭代器和生成器的区别?32. 什么是线程安全?33. 你所遵循的代码规范是什么?请举例说明其要求?44. Python中怎么简单的实现列表去重?55. python 中 yield 的用法?56. 什么是面向对象编程?57. python2和python3的区别?58. 谈谈你对GIL锁对python多线程的影响?89. python是如何进行内存管理的?8二、 Linux基础和数据结构与算法91. 10个常用的Linux命令?92. find和grep的区别?93. 什么是阻塞?什么是非阻塞?94. 描述数组、链表、队列、堆栈的区别?95. 你知道几
2、种排序,讲一讲你最熟悉的一种?9三、 Web框架101.django 中当一个用户登录 A 应用服务器(进入登录状态),然后下次请求被 nginx 代理到 B 应用服务器会出现什么影响?102.跨域请求问题django怎么解决的(原理)103.请解释或描述一下Django的架构104.django对数据查询结果排序怎么做,降序怎么做,查询大于某个字段怎么做105.说一下Django,MIDDLEWARES中间件的作用?106.你对Django的认识?107. Django重定向你是如何实现的?用的什么状态码?118.ngnix的正向代理与反向代理?119. Tornado 的核是什么?1110
3、.Django 本身提供了 runserver,为什么不能用来部署?11四、 网络编程和前端121.AJAX是什么,如何使用AJAX?122. 常见的HTTP状态码有哪些?123. Post和get区别?124.cookie 和session 的区别?135.创建一个简单tcp服务器需要的流程136.请简单说一下三次握手和四次挥手?什么是2msl?为什么要这样做?13五、 爬虫和数据库141.scrapy和scrapy-redis有什么区别?为什么选择redis数据库?142. 你用过的爬虫框架或者模块有哪些?谈谈他们的区别或者优缺点?143.你常用的mysql引擎有哪些?各引擎间有什么区别?
4、154.描述下scrapy框架运行的机制?165.什么是关联查询,有哪些?166.写爬虫是用多进程好?还是多线程好? 为什么?167.数据库的优化?168.常见的反爬虫和应对方法?169.分布式爬虫主要解决什么问题?1710.爬虫过程中验证码怎么处理?17六、 其他17主观题 答案:略.18Python4期模拟面试技术面试题答案一、 python语法1. 请说一下你对迭代器和生成器的区别? 答:(1)迭代器是一个更抽象的概念,任何对象,如果它的类有next方法和iter方法返回自己本身。对于string、list、dict、tuple等这类容器对象,使用for循环遍历是很方便的。在后台for语
5、句对容器对象调用iter()函数,iter()是python的内置函数。iter()会返回一个定义了next()方法的迭代器对象,它在容器中逐个访问容器内元素,next()也是python的内置函数。在没有后续元素时,next()会抛出一个StopIteration异常(2)生成器(Generator)是创建迭代器的简单而强大的工具。它们写起来就像是正规的函数,只是在需要返回数据的时候使用yield语句。每次next()被调用时,生成器会返回它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值)区别:生成器能做到迭代器能做的所有事,而且因为自动创建了_iter_()和next()方法,生成
6、器显得特别简洁,而且生成器也是高效的,使用生成器表达式取代列表解析可以同时节省内存。除了创建和保存程序状态的自动方法,当发生器终结时,还会自动抛出StopIteration异常2. 什么是线程安全?线程安全是在多线程的环境下,能够保证多个线程同时执行时程序依旧运行正确, 而且要保证对于共享的数据可以由多个线程存取,但是同一时刻只能有一个线程进行存取。多线程环境下解决资源竞争问题的办法是加锁来保证存取操作的唯一性。3. 你所遵循的代码规范是什么?请举例说明其要求?PEP81变量常量:大写加下划线 USER_CONSTANT私有变量: 小写和一个前导下划线 _private_valuePython
7、 中不存在私有变量一说,若是遇到需要保护的变量,使用小写和一个前导下划线。但这只是程序员之间的一个约定,用于警告说明这是一个私有变量,外部类不要去访问它。但实际上,外部类还是可以访问到这个变量。内置变量: 小写,两个前导下划线和两个后置下划线 _class_两个前导下划线会导致变量在解释期间被更名。这是为了避免内置变量和其他变量产生冲突。用户定义的变量要严格避免这种风格。以免导致混乱。2函数和方法总体而言应该使用,小写和下划线。但有些比较老的库使用的是混合大小写,即首单词小写,之后每个单词第一个字母大写,其余小写。但现在,小写和下划线已成为规范。私有方法:小写和一个前导下划线这里和私有变量一样
8、,并不是真正的私有访问权限。同时也应该注意一般函数不要使用两个前导下划线(当遇到两个前导下划线时,Python 的名称改编特性将发挥作用)。特殊方法:小写和两个前导下划线,两个后置下划线这种风格只应用于特殊函数,比如操作符重载等。函数参数: 小写和下划线,缺省值等号两边无空格3 类类总是使用驼峰格式命名,即所有单词首字母大写其余字母小写。类名应该简明,精确,并足以从中理解类所完成的工作。常见的一个方法是使用表示其类型或者特性的后缀,例如:SQLEngine,MimeTypes对于基类而言,可以使用一个 Base 或者 Abstract 前缀BaseCookie,AbstractGroup4 模
9、块和包除特殊模块 _init_ 之外,模块名称都使用不带下划线的小写字母。若是它们实现一个协议,那么通常使用lib为后缀,例如:import smtplibimportosimportsys5关于参数5.1 不要用断言来实现静态类型检测。断言可以用于检查参数,但不应仅仅是进行静态类型检测。 Python 是动态类型语言,静态类型检测违背了其设计思想。断言应该用于避免函数不被毫无意义的调用。5.2 不要滥用 *args 和 *kwargs。*args 和 *kwargs 参数可能会破坏函数的健壮性。它们使签名变得模糊,而且代码常常开始在不应该的地方构建小的参数解析器。6 其他6.1 使用 has
10、 或 is 前缀命名布尔元素is_connect=Truehas_member=False6.2 用复数形式命名序列members=user_1,user_26.3 用显式名称命名字典person_address=user_1:10roadWD,user_2:20streethuafu6.4 避免通用名称诸如 list, dict, sequence 或者 element 这样的名称应该避免。6.5 避免现有名称诸如 os, sys 这种系统已经存在的名称应该避免。7 一些数字一行列数 : PEP 8 规定为79 列。根据自己的情况,比如不要超过满屏时编辑器的显示列数。一个函数 : 不要超过3
11、0 行代码, 即可显示在一个屏幕类,可以不使用垂直游标即可看到整个函数。一个类 : 不要超过200 行代码,不要有超过10 个方法。一个模块 不要超过500 行。8 验证脚本可以安装一个 pep8 脚本用于验证你的代码风格是否符合 PEP8。4. Python中怎么简单的实现列表去重?Set5. python 中 yield 的用法?答: yield简单说来就是一个生成器,这样函数它记住上次返 回时在函数体中的位置。对生成器第 二次(或n 次)调用跳转至该函 次)调用跳转至该函 数。6. 什么是面向对象编程?面向对象编程是一种解决软件复用的设计和编程方法。 这种方法把软件系统中相近相似的操作逻
12、辑和操作 应用数据、状态,以类的型式描述出来,以对象实例的形式在软件系统中复用,以达到提高软件开发效率的作用。7. python2和python3的区别?1.性能Py3.0运行 pystone benchmark的速度比Py2.5慢30%。Guido认为Py3.0有极大的优化空间,在字符串和整形操作上可以取得很好的优化结果。Py3.1性能比Py2.5慢15%,还有很大的提升空间。2.编码Py3.X源码文件默认使用utf-8编码3. 语法1)去除了,全部改用!=2)去除,全部改用repr()3)关键词加入as 和with,还有True,False,None4)整型除法返回浮点数,要得到整型结果,
13、请使用/5)加入nonlocal语句。使用noclocal x可以直接指派外围(非全局)变量6)去除print语句,加入print()函数实现相同的功能。同样的还有 exec语句,已经改为exec()函数7)改变了顺序操作符的行为,例如x bytes) or .decode() (bytes - str)方法相互转化。3)dict的.keys()、.items 和.values()方法返回迭代器,而之前的iterkeys()等函数都被废弃。同时去掉的还有dict.has_key(),用 in替代它吧6.面向对象1)引入抽象基类(Abstraact Base Classes,ABCs)。2)容器
14、类和迭代器类被ABCs化。3)迭代器的next()方法改名为_next_(),并增加内置函数next(),用以调用迭代器的_next_()方法4)增加了abstractmethod和 abstractproperty两个 decorator,编写抽象方法(属性)更加方便。7.异常1)所以异常都从 BaseException继承,并删除了StardardError2)去除了异常类的序列行为和.message属性3)用 raise Exception(args)代替 raise Exception, args语法4)捕获异常的语法改变,引入了as关键字来标识异常实例5)异常链,因为_context
15、_在3.0a1版本中没有实现8.模块变动1)移除了cPickle模块,可以使用pickle模块代替。最终我们将会有一个透明高效的模块。2)移除了imageop模块3)移除了 audiodev, Bastion, bsddb185, exceptions, linuxaudiodev, md5, MimeWriter, mimify, popen2,rexec, sets, sha, stringold, strop, sunaudiodev, timing和xmllib模块4)移除了bsddb模块(单独发布,可以从http:/www.jcea.es/programacion/pybsddb.h
16、tm获取)5)移除了new模块6)os.tmpnam()和os.tmpfile()函数被移动到tmpfile模块下7)tokenize模块现在使用bytes工作。主要的入口点不再是generate_tokens,而是 tokenize.tokenize()9.其它1)xrange() 改名为range(),要想使用range()获得一个list,必须显式调用: list(range(10)0, 1, 2, 3, 4, 5, 6, 7, 8, 92)bytes对象不能hash,也不支持 b.lower()、b.strip()和b.split()方法,但对于后两者可以使用 b.strip(bntr
17、 f)和b.split(b )来达到相同目的3)zip()、map()和filter()都返回迭代器。而apply()、 callable()、coerce()、 execfile()、reduce()和reload()函数都被去除了现在可以使用hasattr()来替换 callable(). hasattr()的语法如:hasattr(string, _name_)4)string.letters和相关的.lowercase和.uppercase被去除,请改用string.ascii_letters 等5)如果x y的不能比较,抛出TypeError异常。2.x版本是返回伪随机布尔值的6)_
18、getslice_系列成员被废弃。ai:j根据上下文转换为a._getitem_(slice(I, j)或 _setitem_和_delitem_调用7)file类被废弃8. 谈谈你对GIL锁对python多线程的影响?GIL的全称是Global Interpreter Lock(全局解释器锁),来源是python设计之初的考虑,为了数据安全所做的决定。每个CPU在同一时间只能执行一个线程(在单核CPU下的多线程其实都只是并发,不是并行,并发和并行从宏观上来讲都是同时处理多路请求的概念。但并发和并行又有区别,并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。
19、)在Python多线程下,每个线程的执行方式:1、获取GIL2、执行代码直到sleep或者是python虚拟机将其挂起。3、释放GIL 可见,某个线程想要执行,必须先拿到GIL,我们可以把GIL看作是“通行证”,并且在一个python进程中,GIL只有一个。拿不到通行证的线程,就不允许进入CPU执行。在Python2.x里,GIL的释放逻辑是当前线程遇见IO操作或者ticks计数达到100(ticks可以看作是Python自身的一个计数器,专门做用于GIL,每次释放后归零,这个计数可以通过 sys.setcheckinterval 来调整),进行释放。而每次释放GIL锁,线程进行锁竞争、切换线
20、程,会消耗资源。并且由于GIL锁存在,python里一个进程永远只能同时执行一个线程(拿到GIL的线程才能执行)。 IO密集型代码(文件处理、网络爬虫等),多线程能够有效提升效率(单线程下有IO操作会进行IO等待,造成不必要的时间浪费,而开启多线程能在线程A等待时,自动切换到线程B,可以不浪费CPU的资源,从而能提升程序执行效率),所以多线程对IO密集型代码比较友好。9. python是如何进行内存管理的?一、垃圾回收:python不像C+,Java等语言一样,他们可以不用事先声明变量类型而直接对变量进行赋值。对Python语言来讲,对象的类型和内存都是在运行时确定的。这也是为什么我们称Pyt
21、hon语言为动态类型的原因(这里我们把动态类型可以简单的归结为对变量内存地址的分配是在运行时自动判断变量类型并对变量进行赋值)。二、引用计数:Python采用了类似Windows内核对象一样的方式来对内存进行管理。每一个对象,都维护这一个对指向该对对象的引用的计数。当变量被绑定在一个对象上的时候,该变量的引用计数就是1,(还有另外一些情况也会导致变量引用计数的增加),系统会自动维护这些标签,并定时扫描,当某标签的引用计数变为0的时候,该对就会被回收。三、内存池机制Python的内存机制以金字塔行,-1,-2层主要有操作系统进行操作,第0层是C中的malloc,free等内存分配和释放函数进行操
22、作;第1层和第2层是内存池,有Python的接口函数PyMem_Malloc函数实现,当对象小于256K时有该层直接分配内存;第3层是最上层,也就是我们对Python对象的直接操作;在 C 中如果频繁的调用 malloc 与 free 时,是会产生性能问题的.再加上频繁的分配与释放小块的内存会产生内存碎片. Python 在这里主要干的工作有:如果请求分配的内存在1256字节之间就使用自己的内存管理系统,否则直接使用 malloc.这里还是会调用 malloc 分配内存,但每次会分配一块大小为256k的大块内存.经由内存池登记的内存到最后还是会回收到内存池,并不会调用 C 的 free 释放掉
23、.以便下次使用.对于简单的Python对象,例如数值、字符串,元组(tuple不允许被更改)采用的是复制的方式(深拷贝?),也就是说当将另一个变量B赋值给变量A时,虽然A和B的内存空间仍然相同,但当A的值发生变化时,会重新给A分配空间,A和B的地址变得不再相同二、 Linux基础和数据结构与算法1. 10个常用的Linux命令?答案:略2. find和grep的区别?grep命令是一种强大的文本搜索工具,grep搜索内容串可以是正则表达式,允许对文本文件进行模式查找。如果找到匹配模式, grep打印包含模式的所有行。find通常用来在特定的目录下搜索符合条件的文件,也可以用来搜索特定用户属主的
24、文件。3. 什么是阻塞?什么是非阻塞?阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。例如,我们在CSocket中调用Receive函数,如果缓冲区中没有数据,这个函数就会一直等待,直到有数据才返回。而此时,当前线程还会继续处理各种各样的消息。如果主窗口和调用函数在同一个线程中,除非你在特殊的界面操作函数中调用,其实主界面还是应该可以刷新。socket接收数据的另外一个函数recv则是一个阻塞调用的例子。当socket工作在阻
25、塞模式的时候,如果没有数据的情况下调用该函数,则当前线程就会被挂起,直到有数据为止。非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。4. 描述数组、链表、队列、堆栈的区别?数组与链表是数据存储方式的概念,数组在连续的空间中存储数据,而链表可以在非连续的空间中存储数据;队列和堆栈是描述数据存取方式的概念,队列是先进先出,而堆栈是后进先出;队列和堆栈可以用数组来实现,也可以用链表实现。5. 你知道几种排序,讲一讲你最熟悉的一种?三、 Web框架1.django 中当一个用户登录 A 应用服务器(进入登录状态),然后下次请求被 nginx 代理到 B 应用服
26、务器会出现什么影响?如果用户在A应用服务器登陆的session数据没有共享到B应用服务器,纳米之前的登录状态就没有了。2.跨域请求问题django怎么解决的(原理)启用中间件post请求验证码表单中添加%csrf_token%标签3.请解释或描述一下Django的架构对于Django框架遵循MVC设计,并且有一个专有名词:MVTM全拼为Model,与MVC中的M功能相同,负责数据处理,内嵌了ORM框架V全拼为View,与MVC中的C功能相同,接收HttpRequest,业务处理,返回HttpResponseT全拼为Template,与MVC中的V功能相同,负责封装构造要返回的html,内嵌了模
27、板引擎4.django对数据查询结果排序怎么做,降序怎么做,查询大于某个字段怎么做排序使用order_by()降序需要在排序字段名前加-查询字段大于某个值:使用filter(字段名_gt=值)5.说一下Django,MIDDLEWARES中间件的作用?答:中间件是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。6.你对Django的认识?Django是走大而全的方向,它最出名的是其全自动化的管理后台:只需要使用起ORM,做简单的对象定义,它就能自动生成数据库结构、以及全功能的管理后台。Django内置的ORM跟框架内的其他模
28、块耦合程度高。应用程序必须使用Django内置的ORM,否则就不能享受到框架内提供的种种基于其ORM的便利;理论上可以切换掉其ORM模块,但这就相当于要把装修完毕的房子拆除重新装修,倒不如一开始就去毛胚房做全新的装修。Django的卖点是超高的开发效率,其性能扩展有限;采用Django的项目,在流量达到一定规模后,都需要对其进行重构,才能满足性能的要求。Django适用的是中小型的网站,或者是作为大型网站快速实现产品雏形的工具。Django模板的设计哲学是彻底的将代码、样式分离; Django从根本上杜绝在模板中进行编码、处理数据的可能。7. Django重定向你是如何实现的?用的什么状态码?
29、使用HttpResponseRedirectredirect和reverse状态码:302,3018.ngnix的正向代理与反向代理?答:正向代理 是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。反向代理正好相反,对于客户端而言它就像是原始服务器,并且客户端不需要进行任何特别的设置。客户端向反向代理的命名空间中的内容发送普通请求,接着反向代理将判断向何处(原始服务器)转交请求,并将获得的内容返
30、回给客户端,就像这些内容原本就是它自己的一样。9. Tornado 的核是什么?Tornado 的核心是 ioloop 和 iostream 这两个模块,前者提供了一个高效的 I/O 事件循环,后者则封装了 一个无阻塞的 socket 。通过向 ioloop 中添加网络 I/O 事件,利用无阻塞的 socket ,再搭配相应的回调 函数,便可达到梦寐以求的高效异步执行。10.Django 本身提供了 runserver,为什么不能用来部署?runserver 方法是调试 Django 时经常用到的运行方式,它使用 Django 自带的WSGI Server 运行,主要在测试和开发中使用,并且
31、runserver 开启的方式也是单进程 。 uWSGI 是一个 Web 服务器,它实现了 WSGI 协议、uwsgi、http 等协议。注意 uwsgi 是一种通信协议,而 uWSGI 是实现 uwsgi 协议和 WSGI 协议的 Web 服务器。uWSGI 具有超快的性能、低内存占用和多 app 管理等优点,并且搭配着 Nginx就是一个生产环境了,能够将用户访问请求与应用 app 隔离开,实现真正的部署 。相比来讲,支持的并发量更高,方便管理多进程,发挥多核的优势,提升性能。四、 网络编程和前端1.AJAX是什么,如何使用AJAX?ajax(异步的javascript 和xml) 能够刷
32、新局部网页数据而不是重新加载整个网页。第一步,创建xmlhttprequest对象,var xmlhttp =new XMLHttpRequest();XMLHttpRequest对象用来和服务器交换数据。第二步,使用xmlhttprequest对象的open()和send()方法发送资源请求给服务器。第三步,使用xmlhttprequest对象的responseText或responseXML属性获得服务器的响应。第四步,onreadystatechange函数,当发送请求到服务器,我们想要服务器响应执行一些功能就需要使用onreadystatechange函数,每次xmlhttpreque
33、st对象的readyState发生改变都会触发onreadystatechange函数。2. 常见的HTTP状态码有哪些?200 OK301 Moved Permanently302 Found304 Not Modified307 Temporary Redirect400 Bad Request401 Unauthorized403 Forbidden404 Not Found410 Gone500 Internal Server Error501 Not Implemented3. Post和get区别?1、GET请求,请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数用&
34、连接。URL的编码格式采用的是ASCII编码,而不是uniclde,即是说所有的非ASCII字符都要编码之后再传输。POST请求:POST请求会把请求的数据放置在HTTP请求包的包体中。上面的item=bandsaw就是实际的传输数据。因此,GET请求的数据会暴露在地址栏中,而POST请求则不会。2、传输数据的大小在HTTP规范中,没有对URL的长度和传输的数据大小进行限制。但是在实际开发过程中,对于GET,特定的浏览器和服务器对URL的长度有限制。因此,在使用GET请求时,传输数据会受到URL长度的限制。对于POST,由于不是URL传值,理论上是不会受限制的,但是实际上各个服务器会规定对PO
35、ST提交数据大小进行限制,Apache、IIS都有各自的配置。3、安全性POST的安全性比GET的高。这里的安全是指真正的安全,而不同于上面GET提到的安全方法中的安全,上面提到的安全仅仅是不修改服务器的数据。比如,在进行登录操作,通过GET请求,用户名和密码都会暴露再URL上,因为登录页面有可能被浏览器缓存以及其他人查看浏览器的历史记录的原因,此时的用户名和密码就很容易被他人拿到了。除此之外,GET请求提交的数据还可能会造成Cross-site request frogery攻击。4.cookie 和session 的区别?1、cookie数据存放在客户的浏览器上,session数据放在服务
36、器上。2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当使用session。3、session会在一定时间内保存在服务器上。当访问增多,会比较占用服务器的性能考虑到减轻服务器性能方面,应当使用COOKIE。4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。5、建议: 将登陆信息等重要信息存放为SESSION 其他信息如果需要保留,可以放在COOKIE中5.创建一个简单tcp服务器需要的流程1.socket创建一个套接字2.bind绑定ip和port3.listen使套接字变为可以被动链接4.acce
37、pt等待客户端的链接5.recv/send接收发送数据6.请简单说一下三次握手和四次挥手?什么是2msl?为什么要这样做?2MSL即两倍的MSL,TCP的TIME_WAIT状态也称为2MSL等待状态,当TCP的一端发起主动关闭,在发出最后一个ACK包后,即第3次握 手完成后发送了第四次握手的ACK包后就进入了TIME_WAIT状态,必须在此状态上停留两倍的MSL时间,等待2MSL时间主要目的是怕最后一个 ACK包对方没收到,那么对方在超时后将重发第三次握手的FIN包,主动关闭端接到重发的FIN包后可以再发一个ACK应答包。在TIME_WAIT状态 时两端的端口不能使用,要等到2MSL时间结束才
38、可继续使用。当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。不过在实际应用中可以通过设置 SO_REUSEADDR选项达到不必等待2MSL时间结束再使用此端口。五、 爬虫和数据库1.scrapy和scrapy-redis有什么区别?为什么选择redis数据库?1) scrapy是一个Python爬虫框架,爬取效率极高,具有高度定制性,但是不支持分布式。而scrapy-redis一套基于redis数据库、运行在scrapy框架之上的组件,可以让scrapy支持分布式策略,Slaver端共享Master端redis数据库里的item队列、请求队列和请求指纹集合。2) 为什么选择redis数
39、据库,因为redis支持主从同步,而且数据都是缓存在内存中的,所以基于redis的分布式爬虫,对请求和数据的高频读取效率非常高。2. 你用过的爬虫框架或者模块有哪些?谈谈他们的区别或者优缺点?Python自带:urllib,urllib2第 三 方:requests框 架:Scrapyurllib和urllib2模块都做与请求URL相关的操作,但他们提供不同的功能。urllib2.:urllib2.urlopen可以接受一个Request对象或者url,(在接受Request对象时候,并以此可以来设置一个URL 的headers),urllib.urlopen只接收一个urlurllib 有u
40、rlencode,urllib2没有,因此总是urllib,urllib2常会一起使用的原因scrapy是封装起来的框架,他包含了下载器,解析器,日志及异常处理,基于多线程, twisted的方式处理,对于固定单个网站的爬取开发,有优势,但是对于多网站爬取 100个网站,并发及分布式处理方面,不够灵活,不便调整与括展。request 是一个HTTP库, 它只是用来,进行请求,对于HTTP请求,他是一个强大的库,下载,解析全部自己处理,灵活性更高,高并发与分布式部署也非常灵活,对于功能可以更好实现.Scrapy优缺点:优点:scrapy 是异步的采取可读性更强的xpath代替正则强大的统计和lo
41、g系统同时在不同的url上爬行支持shell方式,方便独立调试写middleware,方便写一些统一的过滤器通过管道的方式存入数据库缺点:基于python的爬虫框架,扩展性比较差基于twisted框架,运行中的exception是不会干掉reactor,并且异步框架出错后是不会停掉其他任务的,数据出错后难以察觉。3.你常用的mysql引擎有哪些?各引擎间有什么区别?主要 MyISAM 与 InnoDB 两个引擎,其主要区别如下:一、InnoDB 支持事务,MyISAM 不支持,这一点是非常之重要。事务是一种高级的处理方式,如在一些列增删改中只要哪个出错还可以回滚还原,而 MyISAM就不可以了
42、;二、MyISAM 适合查询以及插入为主的应用,InnoDB 适合频繁修改以及涉及到安全性较高的应用;三、InnoDB 支持外键,MyISAM 不支持;四、MyISAM 是默认引擎,InnoDB 需要指定;五、InnoDB 不支持 FULLTEXT 类型的索引;六、InnoDB 中不保存表的行数,如 select count(*) from table 时,InnoDB;需要扫描一遍整个表来计算有多少行,但是 MyISAM 只要简单的读出保存好的行数即可。注意的是,当 count(*)语句包含 where 条件时 MyISAM 也需要扫描整个表;七、对于自增长的字段,InnoDB 中必须包含只
43、有该字段的索引,但是在 MyISAM表中可以和其他字段一起建立联合索引;八、清空整个表时,InnoDB 是一行一行的删除,效率非常慢。MyISAM 则会重建表;九、InnoDB 支持行锁(某些情况下还是锁整表,如 update table set a=1 whereuser like %lee%4.描述下scrapy框架运行的机制?答:从start_urls里获取第一批url并发送请求,请求由引擎交给调度器入请求队列,获取完毕后,调度器将请求队列里的请求交给下载器去获取请求对应的响应资源,并将响应交给自己编写的解析方法做提取处理:1. 如果提取出需要的数据,则交给管道文件处理;2. 如果提取出
44、url,则继续执行之前的步骤(发送url请求,并由引擎将请求交给调度器入队列.),直到请求队列里没有请求,程序结束。5.什么是关联查询,有哪些?答:将多个表联合起来进行查询,主要有内连接、左连接、右连接、全连接(外连接)6.写爬虫是用多进程好?还是多线程好? 为什么?答:IO密集型代码(文件处理、网络爬虫等),多线程能够有效提升效率(单线程下有IO操作会进行IO等待,造成不必要的时间浪费,而开启多线程能在线程A等待时,自动切换到线程B,可以不浪费CPU的资源,从而能提升程序执行效率)。在实际的数据采集过程中,既考虑网速和响应的问题,也需要考虑自身机器的硬件情况,来设置多进程或多线程7.数据库的优化?1. 优化索引、SQL 语句、分析慢查询;2. 设计表的时候严格根据数据库的设计范式来设计数据库;3. 使用缓存,把经常访问到的数据而且不需要经常变化的数据放在缓存中,能节约磁盘IO;4. 优化硬件