Totoro - Python
type: channel
link: http://www.totoro.site/index.php/tag/Python
items: 使用Sentry监控展示Django全局错误日志，并通过飞书实时报警
items: django使用django-otp实现后台admin管理系统令牌二次登录，让你的系统更加安全
items: 使用line_profiler分析python代码执行性能
items: Django安装Django-Debug-Toolbar进行系统性能调试
items: 使用python生成阿里云直播流推流拉流地址
items: 使用python生成小程序分享海报
items: python实现excel导入以及excel导出功能
items: 后端配合微信小程序实现消息订阅
items: 微信小程序后端解密手机号
items: Python面试图谱

使用Sentry监控展示Django全局错误日志，并通过飞书实时报警
type: item
date: 2021-08-04T14:38:00+08:00
description: 最近工作上的Django项目，使用了Sentry来做错误日志的监控报警，因为错误日志太多，排查不容易，所以还不如来个主动报警，这样定位排错也很方便，而实际使用情况来看，确实是超级方便的！Sentry在错误监控领域已经是一个很成熟的应用了，支持各种语言多种服务程序的日志监控，如下图：关于更详细的介绍，可以访问官网查看：https://sentry.io/Sentry安装Sentry的安装部分，我这里采用的额时Docker容器部署，关于Docker的安装可以看我的另一篇文章[post cid="65" /]这里具体介绍怎么部署容器版Sentry。部署步骤docker拉取redis postsql 和sentrydocker pull redis docker pull postgres docker pull sentry启动redis和sentrydocker run -d --name sentry-redis redis docker run -d --name sentry-postgres -e POSTGRES_PASSWORD=secret -e POSTGRES_USER=sentry postgres启动Sentry相关docker run --rm sentry config generate-secret-key # 得到secret-key，然后把key复制到下面四行的单引号中 #下面这步会提示输入邮箱和密码 docker run -it --rm -e SENTRY_SECRET_KEY='' --link sentry-postgres:postgres --link sentry-redis:redis sentry upgrade docker run -d -p 9000:9000 --name my-sentry -e SENTRY_SECRET_KEY='' --link sentry-redis:redis --link sentry-postgres:postgres sentry docker run -d --name sentry-cron -e SENTRY_SECRET_KEY='' --link sentry-postgres:postgres --link sentry-redis:redis sentry run cron docker run -d --name sentry-worker-1 -e SENTRY_SECRET_KEY='' --link sentry-postgres:postgres --link sentry-redis:redis sentry run worker访问测试经过上面的步骤，Sentry已经算是部署完毕了，然后打开浏览器，对应的ip地址加9000端口即可访问。打开显示如下图：登录之前设置好的邮箱和密码即可登入系统。新建项目以及基本设置修改系统语言在左侧的user_setting里面可以修改语言为中文简体新建项目在首页点击项目，会出现很多项目模板，选择Django即可Django接入SentryDjango接入Sentry相对来说比较简单，我们这里采用安装Sentry客户端的方式接入。# 首先安装raven pip install raven然后在settings文件中的INSTALLED_APPS里注册Sentry模型INSTALLED_APPS = [ ... # Sentry错误日志监控系统 'raven.contrib.django.raven_compat', ]随后我们返回Sentry网页，点击创建的项目，然后点击齿轮设置图标，点击“客户端密钥（DSN）”，复制该项目的DSN然后再将复制的Sentry DSN粘贴在Settings配置文件中# Sentry错误日志监控系统 RAVEN_CONFIG = { 'dsn': 'http://1283djasssdv2312d12bi21dib1341@192.168.1.124:9000/2', }就这样Django便接入了Sentry，我们在项目里新建一个test_sentry.py文件测试下错误是否能被捕获，内容如下：dsn = "http://1283djasssdv2312d12bi21dib1341@192.168.1.124:9000/2" from raven import Client Client = Client(dsn) try: 1 / 0 except ZeroDivisionError: Client.captureException()执行后去Sentry网页查看，如果出现下图，就说明Sentry起作用了！（因为我已经跑了一段时间了，所以页面有很多别…

django使用django-otp实现后台admin管理系统令牌二次登录，让你的系统更加安全
type: item
date: 2021-07-30T14:12:00+08:00
description: 很多人吐槽django的后台管理系统登录模块不够安全，没有验证码，没有短信。就是裸账号密码登录。确实，django在系统定制这上面做到了极致，用户能改的地方不多，admin管理系统也是一样的被人吐槽简陋，当然，admin系统也不是不能美化，关于美化的相关介绍可以看我的另一篇介绍“simpleui美化”。这里给大家带来的是admin登录的otp二次令牌验证。具体效果如下图，otp token就是令牌验证码：安装安装的话也很简单，首先是先安装两个包，在项目环境里执行：pip install django-otp pip install qrcode然后将 django-otp 添加到 setting.py 和中间件中：INSTALLED_APPS = [ ''' # 安全认证opt 'django_otp', 'django_otp.plugins.otp_totp' ''' ] MIDDLEWARE = [ ''' 'django.contrib.auth.middleware.AuthenticationMiddleware', # 用户认证，注意放在用户认证中间件下面 'django_otp.middleware.OTPMiddleware', ''' ] # opt加密配置，自定义字符配置就行 OTP_TOTP_ISSUER = "otp解码"最后在项目的urls里面加入otp路由配置：from django_otp.admin import OTPAdminSite from django.contrib import admin admin.site.__class__ = OTPAdminSite这样就完成了基础的配置，这时候当你再次打开项目admin后台，就会出现上图出现过的登陆页面了配置登录那现在问题来了，没有otp token我该怎么登录呢，这不是把自己写死了么？别急，等我慢慢说，首先先把刚才在urls里面配置的路由注释掉：# admin.site.__class__ = OTPAdminSite然后打开admin，恢复了老版本，可以正常登录，浏览器链接部分打开“/admin/#otp_totp/totpdevice/”，就会出现如下页面（样式可能不太一样，那是因为我配置了simpleui，无关大雅）这时候点击新增，然后在user部分点击放大镜添加勾选管理员，然后name处写上备注，右下角点击保存，返回列表页面这时候可以看到列表出现了刚才添加的用户，点击右边的qrcode，就会弹出一个二维码。这时候用手机app扫码，就会把动态验证码保存到手机app上，手机app会在文末给出，安卓的是离线的app，提供安装包下载，苹果则是商店下载。这时候基础配置就都完成啦，再把刚才注释掉的urls代码放开就好了，以后每次登录都需要用户名密码和otp的密码才能登陆。关于otp验证技术关于otp验证技术相关介绍，我找了一篇网上的评论介绍，大家可以参考下离线验证码生成器的原理是什么？app下载这里分安卓和ios安卓：https://pan.baidu.com/s/1GgP1iVK7ZKHOZVI_UokiQg ios: 好了，有什么问题都可以联系我。

使用line_profiler分析python代码执行性能
type: item
date: 2021-07-27T11:03:00+08:00
description: 代码的执行性能是程序员需要特别关注的一个点，市面上有很多检测监控python代码执行性能的工具，但是都过于笨重，这里推荐一个更加轻量，粒度更细的性能测试工具包——line_profiler。原理与安装line_profiler作为一个性能测试工具来说是很轻便的，安装也很简单，正常pip安装即可pip install line_profiler安装完成后不需要做额外的过多操作，只需要在要测试的方法之上添加一个@profile装饰器。在程序执行时就会自动将测试代码带入测试程序中进行性能测试。功能测试这里简单的用一段测试代码测试下，新建test_code文件：@profile def test_code(): a = [] a.append('1') a.append('2') a.append('3') a.append('4') a.extend(['4', '5', '6']) c = '' for i in a: c += i print(c) if __name__ == '__main__': test_code()然后运行测试命令：kernprof -l -v test_code.py然后控制台就能看到输出：1234456 Wrote profile results to test_code.py.lprof Timer unit: 1e-06 s Total time: 0.0002404 s File: test_code.py Function: test_code at line 3 Line # Hits Time Per Hit % Time Line Contents ============================================================== 3 @profile 4 def test_code(): 5 1 2.8 2.8 1.2 a = [] 6 7 1 2.5 2.5 1.0 a.append('1') 8 1 1.2 1.2 0.5 a.append('2') 9 1 1.3 1.3 0.5 a.append('3') 10 1 1.2 1.2 0.5 a.append('4') 11 12 1 2.0 2.0 0.8 a.extend(['4', '5', '6']) 13 14 1 0.9 0.9 0.4 c = '' 15 8 7.0 0.9 2.9 for i in a: 16 7 8.0 1.1 3.3 c += i 17 1 213.5 213.5 88.8 print(c)从输出中可以看到每行代码的耗时以及耗时百分比，可以看到for循环和字符串拼接是比较耗时的，这就是line_profiler的整个使用流程，很简单吧。

Django安装Django-Debug-Toolbar进行系统性能调试
type: item
date: 2021-07-24T15:37:00+08:00
description: 在Web应用中，应用性能是一个值得关注的点，我们不应该仅仅局限满足于应用程序“能跑”和“能用”上，还需要考虑到应用程序的执行性能，比如sql语句执行时间，耗时部分在哪里等。简介刚好前不久Django项目里用到过一个测试模块Django-Debug-Toolbar，它是一个内嵌模组，拥有调试ui界面，在Django项目里简单配置后就能在web前端展示的性能调试工具，具体效果如图：从右侧可以看到有很多指标小模块，执行耗时，sql执行耗时，缓存，信号等等，是一个性能调试利器。接下来我们就看看怎么在系统中对此进行配置：配置在终端中执行：python -m pip install django-debug-toolbar然后在Django项目里的settings中的INSTALLED_APPS中添加：INSTALLED_APPS = [ 'debug_toolbar', ]以及添加中间件Middleware，尽量将添加的这句排前一点：MIDDLEWARE = [ # ... 'debug_toolbar.middleware.DebugToolbarMiddleware', # ... ]以及在settings文件中添加白名单配置：INTERNAL_IPS = [ # ... '127.0.0.1', # ... ]然后在settings增加DEBUG_TOOLBAR_​​PANELS基础配置：此设置允许您： #添加默认情况下未启用的内置面板，添加第三方面板，移除内置面板，更改面板的顺序。 DEBUG_TOOLBAR_PANELS = [ 'debug_toolbar.panels.history.HistoryPanel', 'debug_toolbar.panels.versions.VersionsPanel', 'debug_toolbar.panels.timer.TimerPanel', 'debug_toolbar.panels.settings.SettingsPanel', 'debug_toolbar.panels.headers.HeadersPanel', 'debug_toolbar.panels.request.RequestPanel', 'debug_toolbar.panels.sql.SQLPanel', 'debug_toolbar.panels.staticfiles.StaticFilesPanel', 'debug_toolbar.panels.templates.TemplatesPanel', 'debug_toolbar.panels.cache.CachePanel', 'debug_toolbar.panels.signals.SignalsPanel', 'debug_toolbar.panels.logging.LoggingPanel', 'debug_toolbar.panels.redirects.RedirectsPanel', 'debug_toolbar.panels.profiling.ProfilingPanel', ]记得还要引入jquery的jsDEBUG_TOOLBAR_CONFIG = { "JQUERY_URL": '//cdn.bootcss.com/jquery/2.2.4/jquery.min.js', }然后在路由urls里面添加路由：import debug_toolbar from django.conf import settings from django.urls import include, path urlpatterns = [ ... path('__debug__/', include(debug_toolbar.urls)), ]后记就这样配置就完成了。其实Django-Debug-Toolbar有很多第三方的小模组插件的，大家可以去官方文档处查看，点击链接跳转

使用python生成阿里云直播流推流拉流地址
type: item
date: 2020-07-28T10:00:00+08:00
description: 遇到直播相关的业务时，比如手机带货直播等，我们想到的就是寻找大厂提供的相应视频直播流服务。大厂的技术是值得信赖的，以阿里云直播为例，流程是用户方发起直播任务，相应的调用自己服务接口逻辑生成直播推流和拉流地址，继而拿到推流地址进行推流。推流的视频流就经过阿里云服务处理，然后分发到阿里云自己的cdn，用户则在用户端使用拉流地址进行拉流观看。整个流程就是这样的。这里我们以python语言为例，主要实现产品服务端接收响应生成推流拉流地址的逻辑。话不多说，直接上代码：import time import datetime import hashlib import config def md5_encode(hash_str: str): """""" m = hashlib.md5() m.update(hash_str.encode("utf8")) return m.hexdigest() def create_live_stream_url(app_name: str, stream_name: str): time_ex = datetime.datetime.now() + datetime.timedelta(hours=config.hours) time_sta = time.mktime(time_ex.timetuple()) time_fin = str(int(time_sta)) # 加密key，直播鉴权 push_key = config.push_key pull_key = config.pull_key str_push = "/"+app_name+"/"+stream_name+"-"+time_fin+"-0-0-"+push_key push_url = "rtmp://"+config.push_host+"/"+app_name+"/"+stream_name+"?auth_key="+time_fin+"-0-0-"+md5_encode(str_push) str_view_rtmp = "/"+app_name+"/"+stream_name+"-"+time_fin+"-0-0-"+pull_key str_view_flv = "/"+app_name+"/"+stream_name+".flv"+"-"+time_fin+"-0-0-"+pull_key str_view_m3u8 = "/"+app_name+"/"+stream_name+".m3u8"+"-"+time_fin+"-0-0-"+pull_key rtmp_url = "rtmp://"+config.pull_host+"/"+app_name+"/"+stream_name+"?auth_key="+time_fin+"-0-0-"+md5_encode(str_view_rtmp) flv_url = "http://"+config.pull_host+"/"+app_name+"/"+stream_name+".flv"+"?auth_key="+time_fin+"-0-0-"+md5_encode(str_view_flv) m3u8_url = "http://"+config.pull_host+"/"+app_name+"/"+stream_name+".m3u8"+"?auth_key="+time_fin+"-0-0-"+md5_encode(str_view_m3u8) # print("推流地址: " + push_url) # print("rtmp播流地址: " + rtmp_url) # print("flv播流地址: " + flv_url) # print("m3u8播流地址: " + m3u8_url) return {'push_url': push_url, 'rtmp_url': rtmp_url, 'flv_url': flv_url, 'm3u8_url': m3u8_url} 传入阿里云视频服务中配置的app_name和生成的stream_name，处理生成的4个流地址，注意，地址格式必须按照上述规则生成，否则阿里云在验证地址时候会无法通过，也就是生成的流地址是没用的。

使用python生成小程序分享海报
type: item
date: 2020-07-09T09:07:00+08:00
description: 记得之前工作业务上有实现生成小程序分享海报的需求，但是相比小程序端canvas生成海报还是复杂的多，这里使用的是PIL来画图拼接，最后生成图片，最后保存在本地或者上传到云存储以便后续使用，具体看业务需求。话不多说，这里使用的是python语言，以下为代码import uuid import json import os import requests import config import base64 from PIL import Image, ImageDraw, ImageFont class PosterImage: """海报""" qr_code_base_url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' def __init__(self, avatar, backdrop_path): self.avatar = avatar self.backdrop_path = backdrop_path self.qr_code_url = self.qr_code_base_url + （你的access_token） self.backdrop = Image.open(self.backdrop_path) self.generate_copy_backdrop() def get_qr_code(self, content: str): """生成二维码 pil对象""" def get_stream(self, url, user_id, role, kwargs=None): """获取二维码字节码""" json_data = {'scene': '', 'page': '', 'width': 280, 'auto_color': False, 'is_hyaline': False} # 提交到微信地址 result = requests.post(url, json=json_data, timeout=3, verify=False) self.stream = result.content def get_avatar(self): """获取微信头像""" self.stream = requests.get(url=self.avatar).content def save_stream(self): """将流数据保存至本地文件内,返回文件名""" prefix = uuid.uuid1().hex file_name = f'{prefix}.png' file_path = 'qr_code/' + file_name import os path = os.getcwd()+'/plugins/public/' file_path = os.path.join(path, file_path) with open(file_path, 'wb') as f: f.write(self.stream) return file_path def open_material(self, path): """打开素材 qr_code:背景 qr_code:小程序页面二维码 """ try: self.material = Image.open(path) return self.material except(OSError, NameError): print('OSError, Path:', path) def generate_copy_backdrop(self): """生成背景图拷贝对象,对背景图的操作不会影响原对象""" self.copy_backdrop = self.backdrop.copy().convert('RGB') self.copy_backdrop_draw = ImageDraw.Draw(self.copy_backdrop) def set_font(self, css_path: str = None, fill: tuple = (0, 0, 0), size: int = 36): """设定字体""" import os path = os.getcwd() path = os.path.join(path, "static/Alibaba-PuHuiTi-Bold.ttf") self.font = ImageFont.truetype(path, size=size) self.font_fill = fill def synthesis(self, img, x: float, y: float, size=None): """合成图片 :p…

python实现excel导入以及excel导出功能
type: item
date: 2020-07-07T13:59:00+08:00
description: 之前在做后台管理系统时候，有导出和导入excel的需求，其实不难，很快就用xlrd和xlwt实现了。[scode type="blue"]首先先安装xlrd和xlwt[/scode]import xlrd import xlwt[scode type="blue"]导入excel业务实现[/scode]def xls_import(): """学生导入""" form = validators.XlsImportStudent().validate_() file = request.files.get('file') filename = f'{uuid.uuid1().hex}.{form.file_extension.data}' # 保存文件 file_path = 'inxlsx/' + filename path = os.getcwd() + '/plugins/public/' file_path = os.path.join(path, file_path) file.save(file_path + filename) data = open_excel(file=file_path + filename).sheets()[0] nrows = data.nrows pass_num = 0 success_num = 0 for i in range(1, nrows): # 判断学生是否存在 student = Student.query.filter_by(name=data.row_values(i)[0], phone=data.row_values(i)[1]).first() if student: pass_num += 1 pass else: # 数据处理 # 性别 gender = data.row_values(i)[5] if gender == "男": gender_int = 1 else: gender_int = 2 # 政治面貌 political = data.row_values(i)[10] if political == "群众": political_int = 1 elif political == "中共共青团员": political_int = 2 elif political == "中共预备党员": political_int = 3 elif political == "中共党员": political_int = 4 else: political_int = 5 # 最高学历 education = data.row_values(i)[15] if education == "小学": education_int = 1 elif education == "初中": education_int = 2 elif education == "高中": education_int = 3 elif education == "大专": education_int = 4 elif education == "本科": education_int = 5 elif education == "硕士研究生": education_int = 6 elif education == "博士研究生": education_int = 7 else: education_int = 8 # 日期处理 birthday = data.row_values(i)[4] # print(birthday) birthday = datetime.date.fromordinal(int(birthday) + 693594) # dt = datetime.date(1993, 4, 27) # print(dt.toordinal()) graduated_time = data.row_values(i)[17] graduated_time = datetime.date.fromordinal(int(graduated_time) + 693594) # 学校和专业 profession_code = data.row_values(i)[3] profession = Profession.query.filter_by(profession_code=profession_code).first() if profession: Student( bh=uuid.uuid4().hex, name=data.row_values(i)[0], phone=data.row_values(i)[1], id_card=data.row_valu…

后端配合微信小程序实现消息订阅
type: item
date: 2020-07-07T10:14:00+08:00
description: 消息通知是微信小程序里面必不可少的功能，在功能开发中是有很多此类的需求，比如下单成功发送付款通知，付款成功发送订单付款成功通知等。微信小程序的消息通知其实也经历过接口变更以及调用方式变更，以前是直接调用，现在变成了订阅式调用，一次订阅对应一次推送。具体可以查看微信接口文档：微信消息订阅文档具体流程是小程序进行消息订阅：后端使用对应的模板id实现相应的消息调用：[scode type="blue"]后端实现[/scode]后端使用python的flask进行逻辑实现。def send_template_msg(openid: str, template_id: str, value): """ 发送模板消息 :param openid:接收者（用户）的 openid :param template_id:微信消息提醒模板编号 :param value:模板内容，不填则下发空模板 :return: """ # 发送模板消息 url = f'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=xxxxxx' data = {"touser": openid, "template_id": template_id, "lang": "zh_CN", "data": value} r = requests.post(url, json=data).content return r def send()： value = { "thing2": { "value": name # 申请人 }, "phone_number3": { "value": phone # 手机号 }, "time4": { "value": create_time.strftime('%Y-%m-%d') # 申请时间 } } result = send_template_msg(user.user_openid, config.TEMPLATE_ID_1, value) result = json.loads(result.decode()) if result.get('errcode') != 0: raise ViewException(error_code=result.get('errcode'), message=result.get('errmsg'))

微信小程序后端解密手机号
type: item
date: 2020-07-07T09:46:00+08:00
description: 在微信开发中，会有保存手机号的需求，流程是小程序端调用api获取手机号，再发送到后端保存，注意这个手机号是加密的，这里需要后端在获取后解密。这里用python的flask作为后端实现。[scode type="blue"]表单验证：[/scode]这里需要传入验证参数encryptedData和vinumclass DecodeUserPhoneForm(BaseForm): """解密用户手机号""" encryptedData = wtforms.StringField( validators=[ DataRequired()]) vinum = wtforms.StringField( validators=[ DataRequired()])[scode type="blue"]然后是逻辑处理：[/scode]class WXBizDataCrypt: def __init__(self, appId, sessionKey): self.appId = appId self.sessionKey = sessionKey def decrypt(self, encryptedData, iv): # base64 decode sessionKey = base64.b64decode(self.sessionKey) encryptedData = base64.b64decode(encryptedData) iv = base64.b64decode(iv) cipher = AES.new(sessionKey, AES.MODE_CBC, iv) decrypted = json.loads(self._unpad(cipher.decrypt(encryptedData)).decode()) if decrypted['watermark']['appid'] != self.appId: raise Exception('Invalid Buffer') return decrypted def _unpad(self, s): return s[:-ord(s[len(s)-1:])] def decode_user_phone(): """解密用户手机号""" form = validators.DecodeUserPhoneForm(request.args).validate_() user = get_user_model() encryptedData = form.encryptedData.data + '==' iv = form.vinum.data + '==' pc = WXBizDataCrypt(config.MINI_PROGRAM_APPID, user.user_session_key) mobile_obj = pc.decrypt(encryptedData, iv) mobile = mobile_obj['phoneNumber'] print(mobile) data = { 'mobile': mobile } # 存储号码 todo return ''随即就能获取到解密后的手机号，再进行逻辑处理。

Python面试图谱
type: item
date: 2019-05-08T10:58:00+08:00
description: 面试是一门学问，考验的是你的知识储备，临场发挥。对自己心仪的公司面试成功与否很大程度上靠的是对面试准备与否，是否熟悉相应的回答套路等。面试python岗位也是一样。一 面试流程介绍1.1 python后端职位分析职位分析：招聘信息看什么？1.岗位职责（业务是否感兴趣）2.职位要求（自己是否掌握，查漏补缺）3.公司技术栈（公司使用到哪些技术）看招聘描述，挖掘信息从招聘信息中我们能挖掘到什么？1.你对公司做的业务是否感兴趣2.职位要求中的知识技能是否掌握，面试有多大概率成功3.自己还有哪些知识技能需要查漏补缺有的放矢，针对性准备提升面试成功率1.针对公司的技术栈和要求编写不同的简历2.表现出对职位和公司业务的兴趣3.突出自己的技能优势，提升匹配度（技能与公司要求比较符合）1.2 面试流程与环节后端面试流程学生重基础，社招重项目1.一面问基础2.二面问项目3.三面问设计（设计后端）学生重基础项目经验少，基础很重要1.学历和成绩2.大学所学的计算机课程3.在校项目。实习经验社招重项目社招重视项目和设计1.参与过哪些项目？有没有知名项目2.在项目中承担的职责3.有没有系统设计经验？行为面试非技术性问题1.自我介绍2.口头表达能力3.沟通交流能力HR面试到这里拿到offer可能就很大啦1.薪资待遇（锚定效应，可以提出比期望薪资稍高的待遇）2.职业规划3.自我介绍，沟通交流等1.3 python后端技术栈python语言基础1.语言特点2.语法基础3.高级特性算法与数据结构1.常用算法和数据结构2.分析时间，空间复杂度3.实现常见数据结构和算法编程范式1.面向对象编程2.常用设计模式3.函数式编程操作系统1.常用的linux命令2.进程，线程3.内存管理网络编程1.常用TCP/IP/HTTP协议2.socket编程基础3.python并发库数据库1.mysql常考，索引优化2.关系型和Nosql的使用场景3.redis缓存Python web框架1.常用框架对比，restful2.wsgi原理3.web安全问题系统设计1.设计原则，如何分析2.后端系统常用组件（缓存、数据库、消息队列等）3.技术选型和实现（短网址、feed流系统）技术之外，软实力1.学习能力2.业务理解能力，沟通交流能力3.心态1.4 python初中级工程师技能要求和面试标准初级工程师1.扎实的计算机理论基础2.代码规范，风格良好3.能在指导下靠谱的完成业务需求中级工程师1.扎实的计算机基础和丰富的项目经验2.能独立设计和完成项目需求3.熟悉常用web组件（缓存、消息队列等），具有一定的系统设计能力软实力1.具有产品意识，技术引导产品2.沟通交流能力，团队协作能力3.技术领导能力和影响力面试造核弹，工作拧螺丝1.工作内容和业务紧密相关，需要先了解公司是做什么的2.平台决定成长（业务体量），还是要看公司的规模成都3.准备面试需要有的放矢，跟职位相匹配才行1.5简历书写与自我介绍表现出个人优势，突出关键信息1.基本信息（姓名，学校，学历，联系方式等）2.职业技能（编程语言，框架，数据库，开发工具等）3.关键项目经验（承担职责，用到了哪些技术）简历自我评价1.简历自我评价可有可无2.最终还是面试官评价3.如果要写保证尽量内容简介、态度真诚简历加分项1.知名项目经验2.技术栈比较匹配3.开源项目（github、技术博客、linux等）简历需要注意的1.内容精简，突出重点，一页就好2.注意格式，推荐用pdf，避免hr打开格式乱掉3.信息真实，不弄虚作假。技能要与岗位相符自我介绍说什么1.个人信息2.掌握的技术，参与过的项目3.应聘的岗位，表达对该岗位的看法和兴趣举例：个人信息：你好我是~~工作项目经历：之前就职于~，担任什么，参与过~，对~~比较熟悉求职意向：我希望应聘到这个岗位，~~自我介绍的准备1.早准备2.准备开场白讲稿，面试前多练习3.找一个同伴好友模拟面试，消除紧张心理1.6行为面试常见问题与回答技巧面试官会根据候选人过去的行为评测其胜任能力1.理论依据：行为的连贯性，在旧公司是这样，很可能在新公司也会这样2.人在相似的场景时会倾向于重复以往的行为模式3.评判人的业务能力，沟通交流能力，语言表达能力，抗压能力等行为面试的套路（需要重点注意，一般就是问简历上的项目）1.提问方式：说说你曾经~~~2.说说你做过的这个项目3.说说你碰到过的技术难题？你是如何解决的？有何收获？**star模型（需要按照这个来准备）1.情景（situation）：什么情景下发生的2.任务（task）：你是如何明确你的任务的3.行动（action）：采取了什么样的行动4.结果（result）：结果怎么样？学到了什么？**常见问题：面试官一般会问，你还有什么要问我的吗？1.你可千万别说没了，直接说没了…