模拟面试题总结
1,你最熟悉的Unix环境是CentOS Linux下查询环境变量的命令是env查询脚本定时任务的命令是crontab -l
2,写出在网络爬虫爬取数据的过程中 遇到的防爬虫问题的解决方案
针对爬虫禁止访问:在请求头中使用用户代理user-agent,伪装成浏览器
用户行为分析(并发量、在线时间):使用IP代理池,限制并发量
动态加载数据(Ajax和js):使用selenium或者换用其他平台获取json数据(详情请到:https://www.cnblogs.com/gooseeker/p/5511193.html)
3,使用python编写一个简单的爬虫功能 并写出分析的步骤 写出每一步的详细过程 注意:写出自己的分析过程 以及每一步的详细过程
# -*- coding:utf-8 -*-
import requests,json
from lxml import etree
from retrying import retry
class Proxy(object):
def __init__(self):
self.base_url = 'http://www.data5u.com/free/'
self.header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36'}
self.proxy_pool = []
@retry(stop_max_attempt_number = 3)
def get_html(self):
response = requests.get(self.base_url,headers=self.header) if response.status_code == 200:
html = response.content
e_html = etree.HTML(html)
return e_html
def parse_html(self):
html_text = self.get_html()
proxy = {}
data_list = html_text.xpath('//ul[@class="l2"]')
for data in data_list:
ip_port= {}
proxy['ip'] = data.xpath('./span[1]/li/text()')
proxy['port'] = data.xpath('./span[2]/li/text()')
proxy['anoy'] = data.xpath('./span[3]/li/a/text()')
proxy['cate'] = data.xpath('./span[4]/li/a/text()')
proxy['country'] = data.xpath('./span[5]/li/a/text()')
proxy['area'] = data.xpath('./span[6]/li/a/text()')
proxy['isp'] = data.xpath('./span[7]/li/a/text()')
proxy['delay'] = data.xpath('./span[8]/li/text()')
proxy['update'] = data.xpath('./span[9]/li/text()')
for k,v in proxy.items():
print(k,'————',v)
if float(proxy['delay'][0].split('秒')[0].strip()) > 1.0:
ip_port['http'] = proxy['ip'][0] +':'+ proxy['port'][0]
print('————当前ip舍弃————')
self.proxy_pool.append(ip_port)
def save_file(self):
with open('5udata可用ip代理.json','w+') as f:
f.seek(0,0)
f.write('[\n')
for item in self.proxy_pool:
data = json.dumps(item) + ',\n'
f.write(data)
f.write(']')
print('数据已经保存完毕')
def run(self):
self.get_html()
self.parse_html()
self.save_file()
def main():
proxy = Proxy()
proxy.run()
if __name__ == '__main__':
main()
分析思路:
- 定义一个Proxy类,用目的url和用户代理初始话类
- 在类中定义一个get_html()函数,通过requests用户向目的url发送页面请求,获取指定url的页面源代码,返回etree类转化的页面对象
- 定义一个解析页面的函数parse_html(),通过xpath获取页面上需要的信息数据,并将获取到的数据存储在字典中,将字典放在数据队列中
- 定义一个save_file()文件保存函数,从存储字典的队列中取出数据并按条保存到本地文件中
4简要说明视图的作用
在Django框架中视图是:定义完成各类对象所需功能的函数,接收请求,处理业务逻辑,返回结果
在MySQL数据中视图是:查询语句执行后返回的结果集,是对若干张基本表的引用,一张续表,查询语句执行的结果,不存储数据,方便操作,增强可读性,更加安全
5 列举你使用过的python网络爬虫所用到的解析数据包(最熟悉的在前)
lxml,python标准库,html5lib
6 列举你使用过的python中的编码方式(最熟悉的在前)
utf-8,ANSI,gbk-2312,big5,iso-8859
7 python3.5语言中的enumerate 意思是带序号地输出对象中的元素
8 十进制99的八进制的表述方式o143
9 列举四种常用的排序算法
冒泡排序、选择排序、插入排序、快速排序
10 列出比较熟悉的爬虫框架
requests、scrapy、pyspider
11 每天早上6点到12点每隔2小时执行一次 /usr/bin/httpd.sh 怎么实现
crontab -e
6-12/2 * * * /usr/bin/httpd.sh restart
12 os.path 和sys.path的区别
os.path:主要用于操作系统本地文件目录
sys.path:主要用于操作python编译器的环境变量
13 deepcopy 和 copy的区别
deepcopy:包含对象里面的子对象的拷贝,原始对象的改变不会造成拷贝里的任何改变
copy:浅拷贝,只拷贝顶层元素,没有拷贝子对象,原始数据改变,拷贝后的对象也会改变
14 说明os 和sys的不同 并列举常用的模块方法
os模块主要是用于用户对底层系统的操作
sys主要是用户对python解释器的操作
两个模块中都有path方法,在os模块中主要用于在系统创建文件和目录,sys模块主要用于修改python解释器的环境参数
15 re模块中match 和search方法有什么不同
match方法是从字符串的第一个字符开始匹配,第一个字符匹配上才开始匹配后面的字符,如果不匹配就停止匹配,返回匹配到的第一段字符串
search方法在字符串中从前往后匹配,可以在字符串中任何位置开始匹配,返回第一个匹配到的第一段字符串
16 如何匹配<html><title></title></html> 得到<html>
re.match(r‘(.+?)<title>’,’<html><title></title></html>’).group(1)
17 通过重写内建函数 实现文件open之前检查文件格式
def open(filename,mode):
import __builtin__
file = __builtin__.open(filename,mode)
if file.read(5) not in("GIF87", "GIF89"):
raise IOError, "not aGIF file"
file.seek(0)
return file
fp = open("sample/test.gif","r")
print len(fp.read()), "bytes"</span>
18 设计实现遍历目录与子目录 抓取.pyc 文件
# coding:utf-8 -*-
import os
lists = []
def get_pyc(def_path=None):
global lists
if not def_path:
def_path = os.getcwd()
os.chdir(def_path)
dirs = os.listdir()
for di in dirs:
if os.path.isfile(di):
index = di.rfind('.')
postfix = di[index:]
if postfix == '.pyc':
lists.append(di)
else:
get_pyc(di)
os.chdir('../')
def main():
dirs = input('请输入插叙路径:')
get_pyc(dirs)
print('当前目录中所有.pyc文件如下:')
for li in lists:
print(li)
if __name__ == "__main__":
main()
19 简述raid原理
磁盘阵列(Redundant Arrays of Independent Disks,RAID),有“独立磁盘构成的具有冗余能力的阵列”之意。
磁盘阵列作为独立系统在主机外直连或通过网络与主机相连。磁盘阵列有多个端口可以被不同主机或不同端口连接。一个主机连接阵列的不同端口可提升传输速度。
和当时PC用单磁盘内部集成缓存一样,在磁盘阵列内部为加快与主机交互速度,都带有一定量的缓冲存储器。主机与磁盘阵列的缓存交互,缓存与具体的磁盘交互数据。
20 简述weblogic 域与server之间的关系
domain是weblogic管理的基本单元,在domain中必须有一个Server,也可以有多个Server ,domain是为了划分不同的应用或统一应用不同价阶段(开发\测试\生产)而设计的,一般在生产环境下我们不原意将两个不同的程序部署到同一个server上,因为任意一个应用出现问题,会直接影响另外一个应用,有了domain就可以将两个不同的应用部署到两个不同的domain中去,domain起到应用逻辑划分的好处。
domain中可以建多个server在cluster环境下,是有多个server的,所以我们需要对这些server的信息进行管理,所以admin server的概念也就出来了,admin server是对其他server进行管理的一个服务器.
21 python是允许多线程的吗 介绍下python 并行计算的一些方法
python允许多线程,多线程通过threading模块中Thread类来实现
并行运行一般使用的是多进程,多线程可以在调用C语言编译的代码块下也可实现并行计算
22 介绍python中的with方法
with还可以很好的处理上下文环境产生的异常,Python对with的处理还很聪明。基本思想是with所求值的对象必须有一个__enter__()方法,一个__exit__()方法。紧跟with后面的语句被求值后,返回对象的__enter__()方法被调用,这个方法的返回值将被赋值给as后面的变量。当with后面的代码块全部被执行完之后,将调用前面返回对象的__exit__()方法,自动将文件关闭退出
23 介绍下*args 和**kwargs的区别
python中的可变参数*args 表示任何多个无名参数,它是一个tuple;**kwargs 表示关键字参数,它是一个dict。并且同时使用*args和**kwargs时,必须*args参数列要在**kwargs前
24 介绍下@classmethod @staticmethod @property区别
@classmethod:类方法装饰器,调用类中的方法装饰目标对象
@staticmethod:静态方法装饰器,是跟类对象没有多大联系的一个函数,被定义后可以被类对象调用
@property:将方法变成对象的一个属性,可以直接访问类对象的属性
25 介绍下python函数参数传递的类型
python中函数参数传递为传引用
对于不可变类型(如数值、字符串、元组等),由于值不可改变,传过去的效果类似C语言里面的传值
对于可变类型(如列表),值可以被修改,实现的效果类似C语言中的传引用
26 __new__ 和 __init__的区别
__new__是在创建对象前调用,创建实例对象并返回实例对象
__init__在实例对象创建完成后调用,并对该对象初始化
27介绍python中yield的用法
yeild具有阻塞函数输出结果,并记录本次执行所有数据(寄存器、时间片等)的功能,在next()或__next__函数作用下逐个输出所有数据
yield用在函数中,函数就是一个生成器,返回可迭代对象在for循环和next()函数配合下可以遍历所有对象
在线程中使用yield可以实现协程
28 Django里QuerySet的get和filter方法的区别
【输入参数】
get 的参数只能是model中定义的那些字段,只支持严格匹配
filter 的参数可以是字段,也可以是扩展的where查询关键字,如in,like等
【返回值】
get 返回值是一个定义的model对象
filter 返回值是一个新的QuerySet对象,然后可以对QuerySet在进行查询返回新的QuerySet对象,支持链式操作QuerySet一个集合对象,可使用迭代或者遍历,切片等,但是不等于list类型(使用一定要注意)
【异常】
get 只有一条记录返回的时候才正常,也就说明get的查询字段必须是主键或者唯一约束的字段。当返回多条记录或者是没有找到记录的时候都会抛出异常
filter 有没有匹配的记录都可以
29简述Django对http请求的执行流程
在接受一个Http请求之前的准备
启动一个支持WSGI网关协议的服务器监听端口等待外界的Http请求,比如Django自带的开发者服务器或者uWSGI服务器。
服务器根据WSGI协议指定相应的Handler来处理Http请求,并且初始化该Handler,在Django框架中由框架自身负责实现这一个Handler。
此时服务器已处于监听状态,可以接受外界的Http请求
当一个http请求到达服务器的时候
服务器根据WSGI协议从Http请求中提取出必要的参数组成一个字典(environ)并传入Handler中进行处理。
在Handler中对已经符合WSGI协议标准规定的http请求进行分析,比如加载Django提供的中间件,路由分配,调用路由匹配的视图等。
返回一个可以被浏览器解析的符合Http协议的HttpResponse。
30 简述Django下的(内建)缓存机制
Django根据设置的缓存方式,浏览器第一次请求时,cache会缓存单个变量或整个网页等内容到硬盘或者内存中,同时设置response头部,当浏览器再次发起请求时,附带f-Modified-Since请求时间到Django,Django 发现f-Modified-Since会先去参数之后,会与缓存中的过期时间相比较,如果缓存时间比较新,则会重新请求数据,并缓存起来然后返回response给客户端,如果缓存没有过期,则直接从缓存中提取数据,返回给response给客户端。
31Django中model的SlugField类型字段有什么用途
SlugField字段是将输入的内容中的空格都替换成‘-’之后保存,Slug 是一个新闻术语,通常是某些东西的短标签。一个slug只能包含字母、数字、下划线或者是连字符,通常用来作为短标签。通常它们是用来放在URL里的。
SlugField字段的Field.db_index自动设置为True。
通常根据另一个值自动生成slug来填充到SlugField的值
32Django中如何加载初始化数据
Django在创建对象时在盗用save()方法后,ORM框架会把对象的属性转换为写入到数据库中,实现对数据库的初始化;通过操作对象,查询数据库,将查询集返回给视图函数,通过模板语言展现在前端页面
33 什么是lambda函数 他有什么用途
lambda函数是匿名函数
匿名函数可以创建小型匿名的函数无需def声明
可以将函数作为参数传递
34 python中如何进行数据类型的转换
Python 内置的常用函数还包括数据类型转换函数,比如 int() 函数可以
把其他数据类型转换为整数,常用的类型转换函数为:
int(x [,base])
将x转换为一个整数
long(x [,base] )
将x转换为一个长整数
float(x)
将x转换到一个浮点数
complex(real [,imag])
创建一个复数
str(x)
将对象 x 转换为字符串
repr(x)
将对象 x 转换为表达式字符串
eval(str)
用来计算在字符串中的有效Python表达式,并返回一个对象
tuple(s)
将序列 s 转换为一个元组
list(s)
将序列 s 转换为一个列表
set(s)
转换为可变集合
dict(d)
创建一个字典。d 必须是一个序列 (key,value)元组。
frozenset(s)
转换为不可变集合
chr(x)
将一个整数转换为一个字符
unichr(x)
将一个整数转换为Unicode字符
ord(x)
将一个字符转换为它的整数值
hex(x)
将一个整数转换为一个十六进制字符串
oct(x)
将一个整数转换为一个八进制字符串
35python中类方法 类实例方法 静态方法有和区别
在类里面定义的函数就是方法,类方法需要@ classmethod 修饰并且有个隐藏参数 cls,实例方法必须有个参数 self, 静态方法必须有 @staticmethod修饰
类和实例都可以访问静态方法,实例可以访问实例方法也可以访问类方法,类可以访问类方法也可以访问实例方法,访问实例方法必须要带参数 self, 可以理解为类其实也是一个实例,类访问实例方法不带参数会报错的.类本身可以访问函数,实例却不行
36 python中pass语句的作用是什么
pass语句什么也不做,一般作为占位符或者创建占位程序,pass语句不会执行任何操作
37介绍下python中range() 和 xrange()函数的用法
range([start,] stop[, step]),根据start与stop指定的范围以及step设定的步长,生成一个序列
xrange用法与range完全相同,所不同的是生成的不是一个数组,而是一个可迭代对象
range比xrange开销要大,原因是range会直接生成一个list对象,而xrange每次调用返回其中的一个值
38 python匹配HTML tag的时候<.*>和<.*?>有什么区别
<.*>会按照贪婪模式匹配,会从第一个“<”开始一直匹配到最后一个“>”,即使中间有“<”和“>”也全部匹配进去,不会停止;
<.*?>按照非贪婪模式匹配,在保证后面的表达式也能正确匹配的前提下尽量多的匹配
39 函数 类方法定义中如何实现可选参数 可选关键词参数
class People(object):
#类方法,用classmethod来进行修饰
@classmethod
def getCountry(cls,*args,**kwargs):
if args:
for arg in args:
print(arg)
if kwargs:
for k,v in kwargs.items():
print(k,'是:',v)
People.getCountry('我是中国人',语言='汉语',首都='北京')
40 请写一段程序 包含迭代器和生成器的使用
G = ( x*2 for x in range(5))
for x in G:
print (G)
41 何时使用标准库 collections 中的deque
deque其实是 double-ended queue 的缩写,翻译过来就是双端队列,它最大的好处就是实现了从队列 头部快速增加和取出对象:
.popleft(),
.appendleft()
但是值得注意的是,list对象的这两种用法的时间复杂度是 O(n) ,也就是说随着元素数量的增加耗时呈 线性上升。而使用deque对象则是 O(1) 的复杂度,所以当你的代码有这样的需求的时候, 一定要记得使用deque。
deque还可以限制队列长度,如果长于队列则会删除
如果是是append则会删除最左端的元素
如果是apppendleft则会删除最右端的元素
collections中有几个非常好用的数据类型
Python拥有一些内置的数据类型,比如str, int, list, tuple, dict等, collections模块在这些内置数据类型的基础上,提供了几个额外的数据类型:
namedtuple(): 生成可以使用名字来访问元素内容的tuple子类
deque: 双端队列,可以快速的从另外一侧追加和推出对象
Counter: 计数器,主要用来计数
OrderedDict: 有序字典
defaultdict: 带有默认值的字典
42 如何使用标准库pdb 调试python程序
在python中使用pdb模块可以进行调试
import pdb
pdb.set_trace()
也可以使用python -m pdb myscript.py这样的方式
43 如何使用装饰器
在不能改能源代码的前提下,增加额外的功能,此时就可以使用装饰器,装饰器是一个实现主体是一个闭包,在原始要装饰的函数上使用@和闭包外层函数名即可装饰该函数,在函数的下方调用原函数名,即可运行
44 参数传递使用的是传递引用还是传递值 为什么
python中函数参数传递为传引用
对于不可变类型(如数值、字符串、元组等),由于值不可改变,传过去的效果类似C语言里面的传值
对于可变类型(如列表),值可以被修改,实现的效果类似C语言中的传引用
45说明 Cpython 的内存管理机制
【引用计数】
每一个Python对象都有一个引用计数器----用于记录有多少其他对象指向(引用)这个对象。它存储在变量 refcnt 中,并通过调用C宏Py_INCREF实现引用计数增加和Py_DECREF实现引用计数减少的操作。 Py_DECREF更复杂点,当引用计数器到零时,它会运行该对象的释放函数,回收该类型的对象
循环引用只能由容器对象创建,因此Python GC不会跟踪整数,字符串等类型。
【垃圾回收】
GC将对象分为3代,每一代对象都有一个计数器和一个阈值。当对象被创建时,阈值会被自动地指派为0,也就是第0代对象。当计数器大于某个阀值,GC就会运行在当前对象代上,回收该对象。没被回收的对象会被移至下一代,并且将相应的计数器复位。下一代的对象保留在下一代
46 写一个函数实现功能:返回1到10亿之间的所有的素数
# -*- coding:utf-8 -*-
import math
def print_prime()
nums = (x for x in range(1,1000000000))
lists = []
for num in nums:
i = 2
# 2太特殊,下面的算法不能直接排除
if num == 2:
print(num)
lists.append(num)
continue
while i < math.ceil(num**0.5)+1:
if (num%i) == 0:
i += 1
break
else:
if i == math.ceil(num**0.5):
lists.append(num)
print(num)
i += 1
print(lists)
return list
if __name__ == ‘__main__’:
prime = print_prime()
print(prime)
47写一个函数实现如下功能: 以升序的方式融合这2个列表 list1 =[2,4,5,9,20,8,7] list2 =[21,25,42,39,8] 并返回融合后的列表 要求: 不能使用python自带的sort list.sort 函数
def mer_sort(lista,listb):
lista.extend(listb)
new_list = lista
for i in range(len(new_list),0,-1):
for y in range(i-1):
if new_list[y] < new_list[y+1]:
continue
else:
new_list[y],new_list[y+1] = new_list[y+1],new_list[y]
return new_list
list1 = [2,4,5,9,20,8,7]
list2 =[21,25,42,39,8]
result = mer_sort(list1,list2)
print(result)
48 在python中 list tuple dict set有什么区别主要的应用场景
list列表,用一对方括号括起来,其中的元素可以是不同的数据类型,可以有重复数据,是可变类型;主要用在数据多,类型不同统一的需要修改的数据结构中
tuple元组,用一对圆括号括起来,元素可以是不同的类型,可以重复,是不可变类型;主要用在主要用在数据类多,类型不同统一的不能修改的数据结构中
dict字典用一对大括号括起来,以键值对的形式保存的数据,键必须是字符串,值可以是任何类型;主要用在需要查询的数据结构中,提高查询效率
set集合用一对大括号括起来,里面的元素基本的数据(数值、字符串等),不能有重复元素;可以用在对数据进行去重和筛选的数据结构中
49 关系型数据库中表与表之间的左连接 内连接 外连接 分别解释下他们的含义和区别
左连接:查询结果显示左表的所有数据和右边连接表中满足where条件的数据
内连接:查询结果仅包含符合连接条件的数据,两张表都要符合连接条件
外连接:连接结果不仅包含符合连接条件的数据还包含不符合连接条件的数据包含左外连接(左连接)、右外连接(右连接)、全外连接
50 python是怎样进行内存管理的
引用计数
python内部使用引用计数,来保持追踪内存中的对象,Python内部记录了对象有多少个引用,即引用计数,当对象被创建时就创建了一个引用计数,当对象不再需要时,这个对象的引用计数为0时,它被垃圾回收。
垃圾回收
、当内存中有不再使用的部分时,垃圾收集器就会把他们清理掉。它会去检查那些引用计数为0的对象,然后清除其在内存的空间。当然除了引用计数为0的会被清除,还有一种情况也会被垃圾收集器清掉:当两个对象相互引用时,他们本身其他的引用已经为0了。
2、垃圾回收机制还有一个循环垃圾回收器, 确保释放循环引用对象(a引用b, b引用a, 导致其引用计数永远不为0)。
内存池
Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。
Python中所有小于256个字节的对象都使用pymalloc实现的分配器,而大的对象则使用系统的 malloc。另外Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。
51 介绍下except的用法和作用
Python的except用来捕获所有异常, 因为Python里面的每次错误都会抛出 一个异常,所以每个程序的错误都被当作一个运行时错误,except一般是结合try和finally一起使用,主要是当指定的代码块出现了预设的异常后,可以捕获该异常,并进行相应的处理,无论是否发生异常finally后面的代码都会执行