抓包与反爬

  • 常见的反爬手段
    • 反爬原因
    • 反爬常见概念
    • 反爬的三个方向
    • 基于身份识别进行反爬
      • 通过headers字段来反爬
      • 通过请求参数来反爬
    • 常见基于爬虫行为进行反爬
      • 基于请求频率或总请求数量
      • 根据爬取行为进行反爬
    • 基于数据加密进行反爬
      • 对响应中含有的数据进行特殊化处理
  • 验证码处理
    • 图片验证码
      • 图片识别引擎
        • tesseract
        • 图片识别引擎环境的安装
        • 图片识别引擎的使用
        • 图片识别引擎的使用扩展
      • 打码平台
        • 常见的打码平台
        • 云打码的使用
      • 常见的验证码的种类
  • chrome浏览器使用方法
    • 新建隐身窗口
    • network的更多功能
      • Perserve log
      • filter过滤
      • 观察特定种类的请求
    • 寻找登录接口
  • JS解析
    • 确定js的位置
      • 观察按钮的绑定js事件
      • 通过search all file 来搜索
    • 观察js的执行过程
    • js2py的使用
      • 具体代码

常见的反爬手段

反爬原因

爬虫占总PV(PV是指页面的访问次数,每打开或刷新一次页面,就算做一个pv)比例较高,这样浪费钱(尤其是三月份爬虫)。
公司可免费查询的资源被批量抓走,丧失竞争力,这样少赚钱。
状告爬虫成功的几率小

反爬常见概念

  • 爬虫:使用任何技术手段,批量获取网站信息的一种方式。关键在于批量。
  • 反爬虫:使用任何技术手段,阻止别人批量获取自己网站信息的一种方式。关键也在于批量。
  • 误伤:在反爬虫的过程中,错误的将普通用户识别为爬虫。误伤率高的反爬虫策略,效果再好也不能用。
  • 拦截:成功地阻止爬虫访问。这里会有拦截率的概念。通常来说,拦截率越高的反爬虫策略,误伤的可能性就越高。因此需要做个权衡。
  • 资源:机器成本与人力成本的总和。

反爬的三个方向

  • 基于身份识别进行反爬
  • 基于爬虫行为进行反爬
  • 基于数据加密进行反爬

基于身份识别进行反爬

通过headers字段来反爬

1.1 通过headers中的User-Agent字段来反爬

  • 反爬原理:爬虫默认情况下没有User-Agent,而是使用模块默认设置
  • 解决方法:请求之前添加User-Agent即可;更好的方式是使用User-Agent池来解决(收集一堆User-Agent的方式,或者是随机生成User-Agent)

1.2 通过referer字段或者是其他字段来反爬

  • 反爬原理:爬虫默认情况下不会带上referer字段,服务器端通过判断请求发起的源头,以此判断请求是否合法
  • 解决方法:添加referer字段

1.3 通过cookie来反爬

  • 反爬原因:通过检查cookies来查看发起请求的用户是否具备相应权限,以此来进行反爬
  • 解决方案:进行模拟登陆,成功获取cookies之后在进行数据爬取

通过请求参数来反爬

2.1 通过从html静态文件中获取请求数据(github登录数据)

  • 反爬原因:通过增加获取请求参数的难度进行反爬
  • 解决方案:仔细分析抓包得到的每一个包,搞清楚请求之间的联系

2.2 通过发送请求获取请求数据

  • 反爬原因:通过增加获取请求参数的难度进行反爬
  • 解决方案:仔细分析抓包得到的每一个包,搞清楚请求之间的联系,搞清楚请求参数的来源

2.3 通过js生成请求参数

  • 反爬原理:js生成了请求参数
  • 解决方法:分析js,观察加密的实现过程,通过js2py获取js的执行结果,或者使用selenium来实现

2.4 通过验证码来反爬

  • 反爬原理:对方服务器通过弹出验证码强制验证用户浏览行为
  • 解决方法:打码平台或者是机器学习的方法识别验证码,其中打码平台廉价易用,更值得推荐

常见基于爬虫行为进行反爬

基于请求频率或总请求数量

1.1 通过请求ip/账号单位时间内总请求数量进行反爬

  • 反爬原理:正常浏览器请求网站,速度不会太快,同一个ip/账号大量请求了对方服务器,有更大的可能性会被识别为爬虫
  • 解决方法:对应的通过购买高质量的ip的方式能够解决问题/购买个多账号

1.2 通过同一ip/账号请求之间的间隔进行反爬

  • 反爬原理:正常人操作浏览器浏览网站,请求之间的时间间隔是随机的,而爬虫前后两个请求之间时间间隔通常比较固定同时时间间隔较短,因此可以用来做反爬
  • 解决方法:请求之间进行随机等待,模拟真实用户操作,在添加时间间隔后,为了能够高速获取数据,尽量使用代理池,如果是账号,则将账号请求之间设置随机休眠

1.3 通过对请求ip/账号每天请求次数设置阈值进行反爬

  • 反爬原理:正常的浏览行为,其一天的请求次数是有限的,通常超过某一个值,服务器就会拒绝响应
  • 解决方法:对应的通过购买高质量的ip的方法/多账号,同时设置请求间随机休眠

根据爬取行为进行反爬

通常在爬取步骤上做分析

2.1 通过js实现跳转来反爬

  • 反爬原理:js实现页面跳转,无法在源码中获取下一页url
  • 解决方法: 多次抓包获取条状url,分析规律

2.2 通过蜜罐(陷阱)获取爬虫ip(或者代理ip),进行反爬

  • 反爬原理:在爬虫获取链接进行请求的过程中,爬虫会根据正则,xpath,css等方式进行后续链接的提取,此时服务器端可以设置一个陷阱url,会被提取规则获取,但是正常用户无法获取,这样就能有效的区分爬虫和正常用户
  • 解决方法: 完成爬虫的编写之后,使用代理批量爬取测试/仔细分析响应内容结构,找出页面中存在的陷阱

2.3 通过假数据反爬

  • 反爬原理:向返回的响应中添加假数据污染数据库,通常家属剧不会被正常用户看到
  • 解决方法: 长期运行,核对数据库中数据同实际页面中数据对应情况,如果存在问题/仔细分析响应内容

2.4 阻塞任务队列

  • 反爬原理:通过生成大量垃圾url,从而阻塞任务队列,降低爬虫的实际工作效率
  • 解决方法: 观察运行过程中请求响应状态/仔细分析源码获取垃圾url生成规则,对URL进行过滤

2.5 阻塞网络IO

  • 反爬原理:发送请求获取响应的过程实际上就是下载的过程,在任务队列中混入一个大文件的url,当爬虫在进行该请求时将会占用网络io,如果是有多线程则会占用线程
  • 解决方法: 观察爬虫运行状态/多线程对请求线程计时/发送请求钱

2.6 运维平台综合审计

  • 反爬原理:通过运维平台进行综合管理,通常采用复合型反爬虫策略,多种手段同时使用
  • 解决方法: 仔细观察分析,长期运行测试目标网站,检查数据采集速度,多方面处理

基于数据加密进行反爬

对响应中含有的数据进行特殊化处理

通常的特殊化处理主要指的就是css数据偏移/自定义字体/数据加密/数据图片/特殊编码格式等
1.1 通过自定义字体来反爬

  • 反爬思路: 使用自有字体文件
  • 解决思路:切换到手机版/解析字体文件进行翻译

1.2 通过css来反爬

  • 反爬思路:源码数据不为真正数据,需要通过css位移才能产生真正数据

  • 解决思路:计算css的偏移
    1.3 通过js动态生成数据进行反爬

  • 反爬原理:通过js动态生成

  • 解决思路:解析关键js,获得数据生成流程,模拟生成数据

1.4 通过数据图片化反爬

  • 58同城短租](https://baise.58.com/duanzu/38018718834984x.shtml)
  • 解决思路:通过使用图片解析引擎从图片中解析数据

1.5 通过编码格式进行反爬

  • 反爬原理: 不适用默认编码格式,在获取响应之后通常爬虫使用utf-8格式进行解码,此时解码结果将会是乱码或者报错
  • 解决思路:根据源码进行多格式解码,或者真正的解码格式

验证码处理

图片验证码

  • 验证码(CAPTCHA)是一种区分用户是计算机还是人的公共全自动程序。
  • 验证码的作用:防止恶意破解密码、刷票、论坛灌水、刷页。
    图片验证码的处理方案
  • 手动输入(input)
  • 图像识别引擎解析:使用光学识别引擎处理图片中的数据,常用于图片数据提取
  • 打码平台: 爬虫常用的验证码解决方案

图片识别引擎

OCR(Optical Character Recognition)是指对文本资料进行扫描成图像文件,然后对图像文件进行分析处理,自动识别获取文字信息及版面信息的软件。

tesseract

  • Tesseract,一款由HP实验室开发由Google维护的开源OCR引擎,特点是开源,免费,支持多语言,多平台。
  • 项目地址:https://github.com/tesseract-ocr/tesseract

图片识别引擎环境的安装

  1. 引擎的安装
  • mac环境下直接执行命令
    brew install --with-training-tools tesseract
  • windows环境下的安装
    可以通过exe安装包安装,下载地址GitHub项目中的wiki。安装完成后,将Tesseract 执行文件的目录加入到PATH中,方便后续调用。
  • linux环境下的安装
    sudo apt-get install tesseract-ocr
  1. Python库的安装
  • PIL用于打开图片文件
    pip/pip3 install pillow
  • pytesseract模块用于从图片中解析数据
    pip/pip3 install pytesseract

图片识别引擎的使用

  • 通过pytesseract模块的 image_to_string 方法就能将打开的图片文件中的数据提取成字符串数据
from PIL import Image
import pytesseract
im = Image.open()
result = pytesseract.image_to_string(im)
print(result)

图片识别引擎的使用扩展

  • tesseract简单使用与训练
  • 其他ocr平台

微软Azure 图像识别:https://azure.microsoft.com/zh-cn/services/cognitive-services/computer-vision/
有道智云文字识别:http://aidemo.youdao.com/ocrdemo
阿里云图文识别:https://www.aliyun.com/product/cdi/
腾讯OCR文字识别:https://cloud.tencent.com/product/ocr

打码平台

常见的打码平台

  1. 云打码:http://www.yundama.com/
    能够解决通用的验证码识别
  2. 极验验证码智能识别辅助:http://jiyandoc.c2567.com/
    能够解决复杂验证码的识别

云打码的使用

  1. 云打码官方接口
    云打码平台提供,实现了两个方法:
  2. indetify:传入图片的响应二进制数即可
  3. indetify_by_filepath:传入图片的路径即可识别
    自己配置
username = 'whoarewe' # 用户名
password = '***' # 密码
appid = 4283 # appid
appkey = '02074c64f0d0bb9efb2df455537b01c3' # appkey
codetype = 1004 # 验证码类型

云打码官方提供的api

#yundama.py
import requests
import json
import timeclass YDMHttp:apiurl = 'http://api.yundama.com/api.php'username = ''password = ''appid = ''appkey = ''def __init__(self, username, password, appid, appkey):self.username = usernameself.password = passwordself.appid = str(appid)self.appkey = appkeydef request(self, fields, files=[]):response = self.post_url(self.apiurl, fields, files)response = json.loads(response)return responsedef balance(self):data = {'method': 'balance', 'username': self.username, 'password': self.password, 'appid': self.appid,'appkey': self.appkey}response = self.request(data)if (response):if (response['ret'] and response['ret'] < 0):return response['ret']else:return response['balance']else:return -9001def login(self):data = {'method': 'login', 'username': self.username, 'password': self.password, 'appid': self.appid,'appkey': self.appkey}response = self.request(data)if (response):if (response['ret'] and response['ret'] < 0):return response['ret']else:return response['uid']else:return -9001def upload(self, filename, codetype, timeout):data = {'method': 'upload', 'username': self.username, 'password': self.password, 'appid': self.appid,'appkey': self.appkey, 'codetype': str(codetype), 'timeout': str(timeout)}file = {'file': filename}response = self.request(data, file)if (response):if (response['ret'] and response['ret'] < 0):return response['ret']else:return response['cid']else:return -9001def result(self, cid):data = {'method': 'result', 'username': self.username, 'password': self.password, 'appid': self.appid,'appkey': self.appkey, 'cid': str(cid)}response = self.request(data)return response and response['text'] or ''def decode(self, filename, codetype, timeout):cid = self.upload(filename, codetype, timeout)if (cid > 0):for i in range(0, timeout):result = self.result(cid)if (result != ''):return cid, resultelse:time.sleep(1)return -3003, ''else:return cid, ''def post_url(self, url, fields, files=[]):# for key in files:#     files[key] = open(files[key], 'rb');res = requests.post(url, files=files, data=fields)return res.text username = 'whoarewe' # 用户名password = '***' # 密码appid = 4283 # appidappkey = '02074c64f0d0bb9efb2df455537b01c3' # appkeyfilename = 'getimage.jpg' # 文件位置codetype = 1004 # 验证码类型# 超时
timeout = 60def indetify(response_content):if (username == 'username'):print('请设置好相关参数再测试')else:# 初始化yundama = YDMHttp(username, password, appid, appkey)# 登陆云打码uid = yundama.login();print('uid: %s' % uid)# 查询余额balance = yundama.balance();print('balance: %s' % balance)# 开始识别,图片路径,验证码类型ID,超时时间(秒),识别结果cid, result = yundama.decode(response_content, codetype, timeout)print('cid: %s, result: %s' % (cid, result))return resultdef indetify_by_filepath(file_path):if (username == 'username'):print('请设置好相关参数再测试')else:# 初始化yundama = YDMHttp(username, password, appid, appkey)# 登陆云打码uid = yundama.login();print('uid: %s' % uid)# 查询余额balance = yundama.balance();print('balance: %s' % balance)# 开始识别,图片路径,验证码类型ID,超时时间(秒),识别结果cid, result = yundama.decode(file_path, codetype, timeout)print('cid: %s, result: %s' % (cid, result))return resultif __name__ == '__main__':pass

常见的验证码的种类

  1. url地址不变,验证码不变
    这是验证码里面非常简单的一种类型,对应的只需要获取验证码的地址,然后请求,通过打码平台识别即可

  2. url地址不变,验证码变化
    这种验证码的类型是更加常见的一种类型
    通过cookie来验证之前获取的验证码和最后提交的验证码是同一个验证码。在请求页面,请求验证码,提交验证码的到时候需要保证cookie的一致性,对此可以使用requests.session来解决。

chrome浏览器使用方法

新建隐身窗口

使用隐身窗口,首次打开网站,不会带上cookie,能够观察页面的获取情况,包括对方服务器如何设置cookie在本地

network的更多功能

Perserve log

默认情况下,页面发生跳转之后,之前的请求url地址等信息都会消失,勾选perserve log后之前的请求都会被保留。

filter过滤

在url地址很多的时候,可以在filter中输入部分url地址,对所有的url地址起到一定的过滤效果。

观察特定种类的请求

默认是选择的all,即会观察到所有种类的请求
比如常见的选项:

  • XHR:大部分情况表示ajax请求
  • JS:js请求
  • CSS:css请求
    不清楚一个请求是否为ajax请求的时候,直接选择all,从前往后观察即可,其中js,css,图片等不去观察即可。

寻找登录接口

  1. 寻找action对的url地址

    这个地址就是在登录的form表单中action对应的url地址,进行表单提交的地址,对应的,提交的数据,仅仅需要:用户名的input标签中,name的值作为键,用户名作为值,密码的input标签中,name的值作为键,密码作为值即可
  2. 通过抓包寻找登录的url地址


手机版中,依然有参数,但是参数的个数少一些
总结

  1. 使用隐身窗口的主要目的是为了避免首次打开网站携带cookie的问题
  2. chrome的network中,perserve log选项能够在页面发生跳转之后任然能够观察之前的请求
  3. 确定登录的地址有两种方法:
    • 寻找from表单action的url地址
    • 通过抓包获取

JS解析

确定js的位置

观察按钮的绑定js事件

通过search all file 来搜索


观察js的执行过程

找到js的位置之后,通过观察js的位置,找到js具体在如何执行,可以通过python程序来模拟js的执行,或者是使用类似js2py直接把js代码转化为python程序去执行。

- 1:继续执行到下一个断点
- 2:进入调用的函数中
- 3:从调用的函数中跳出来

js2py的使用

  • js2py是一个js的翻译工具,也是一个通过纯python实现的js的解释器,github上源码与示例
  • js的执行思路:使用python程序实现js的执行时候,需要观察的js的每一个步骤,非常麻烦。所以更多的时候我们会选择使用类似js2py的模块去执行js。
  • 具体实现
  1. 定位进行登录js代码
formSubmit: function() {var e, t = {};$(".login").addEventListener("click", function() {t.phoneNum = $(".phonenum").value,t.password = $(".password").value,e = loginValidate(t),t.c1 = c1 || 0,e.flag ? ajaxFunc("get", "http://activity.renren.com/livecell/rKey", "", function(e) {var n = JSON.parse(e).data;if (0 == n.code) {t.password = t.password.split("").reverse().join(""),setMaxDigits(130);var o = new RSAKeyPair(n.e,"",n.n), r = encryptedString(o, t.password);t.password = r,t.rKey = n.rkey} elsetoast("公钥获取失败"),t.rKey = "";ajaxFunc("post", "http://activity.renren.com/livecell/ajax/clog", t, function(e) {var e = JSON.parse(e).logInfo;0 == e.code ? location.href = localStorage.getItem("url") || "" : toast(e.msg || "登录出错")})}) : toast(e.msg)})}

js代码解析:

  1. 我们要登录需要对密码进行加密和获取rkey字段的值
  2. rkey字段的值,直接发送请求rkey请求就可以获得
  3. 密码是先反转然后使用RSA进行加密, js代码很复杂, 通过在python中执行js来实现

实现思路:

  1. 使用session发送rKey获取登录需要信息

    • url: http://activity.renren.com/livecell/rKey
    • 方法: get
  2. 根据获取信息对密码进行加密
    2.1 准备用户名和密码
    2.2 使用js2py生成js的执行环境:context
    2.3 拷贝使用到js文件的内容到本项目中
    2.4 读取js文件的内容,使用context来执行它们
    2.5 向context环境中添加需要数据
    2.6 使用context执行加密密码的js字符串
    2.7 通过context获取加密后密码信息
  3. 使用session发送登录请求
    • URL: http://activity.renren.com/livecell/ajax/clog
    • 请求方法: POST
    • 数据:
phoneNum: xxxxxxx
password: (加密后生产的)
c1: 0
rKey: rkey请求获取的

具体代码

提前下载js文件到本地:
BigInt.js
RSA.js
Barrett.js

import requests
import json
import js2py# - 实现思路:
#   - 使用session发送rKey获取登录需要信息
#     - url: http://activity.renren.com/livecell/rKey
#     - 方法: get
#  获取session对象
session = requests.session()
headers = {"User-Agent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Mobile Safari/537.36","X-Requested-With": "XMLHttpRequest","Content-Type":"application/x-www-form-urlencoded"
}
# 设置session的请求头信息
session.headers = headersresponse = session.get("http://activity.renren.com/livecell/rKey")
# print(response.content.decode())
n = json.loads(response.content)['data']#   - 根据获取信息对密码进行加密
#     - 准备用户名和密码
phoneNum = "131..."
password = "****"
#     - 使用js2py生成js的执行环境:context
context = js2py.EvalJs()
#     - 拷贝使用到js文件的内容到本项目中
#     - 读取js文件的内容,使用context来执行它们
with open("BigInt.js", 'r', encoding='utf8') as f:context.execute(f.read())with open("RSA.js", 'r', encoding='utf8') as f:context.execute(f.read())
with open("Barrett.js", 'r', encoding='utf8') as f:context.execute(f.read())# - 向context环境中添加需要数据
context.t = {'password': password}
context.n = n
#     - 执行加密密码的js字符
js = '''t.password = t.password.split("").reverse().join(""),setMaxDigits(130);var o = new RSAKeyPair(n.e,"",n.n), r = encryptedString(o, t.password);'''
context.execute(js)
# - 通过context获取加密后密码信息
# print(context.r)
password = context.r
#   - 使用session发送登录请求
#     - URL: http://activity.renren.com/livecell/ajax/clog
#     - 请求方法: POST
#     - 数据:
#       - phoneNum: 15565280933
#       - password: (加密后生产的)
#       - c1: 0
#       - rKey: rkey请求获取的
data = {'phoneNum': '131....','password': password,'c1':0,'rKey':n['rkey']
}# print(session.headers)
response = session.post("http://activity.renren.com/livecell/ajax/clog", data=data)
print(response.content.decode())# 访问登录的资源
response = session.get("http://activity.renren.com/home#profile")
print(response.content.decode())

小结

  1. 通过在chrome中观察元素的绑定事件可以确定js
  2. 通过在chrome中search all file 搜索关键字可以确定js的位置
  3. 观察js的数据生成过程可以使用添加断点的方式观察
  4. js2py的使用
    • 需要准备js的内容
    • 生成js的执行环境
    • 在执行环境中执行js的字符串,传入数据,获取结果

数据收集-抓包与反爬相关推荐

  1. 五 Pathon爬虫之抓包与反爬以及反爬解决方案

    一 介绍 1.1 服务器反爬的原因 爬虫占总PV(PV是指页面的访问次数,每打开或刷新一次页面,就算做一个pv)比例较高,这样浪费钱(尤其是三月份爬虫). 三月份爬虫是个什么概念呢?每年的三月份我们会 ...

  2. 实习周记1(sdk了解、fiddler抓包、反编译工具)

    文章目录 本周知识清单 SDK为游戏提供哪些功能 什么是SDK SDK在游戏中提供的功能 SDK技术特点 简洁易用 稳定 高效 模块化开发 组件化开发 插件化开发 SDK各功能模块如何实现的 制作SD ...

  3. fiddler不能抓取浏览器数据_抓包软件 Fiddler 了解一下?

    学会如何抓包,是爬虫的必备技能,甚至可以说,不会抓包就等同于不会爬虫. 那我们怎样抓包呢?如果直接抓取浏览器上的内容,可以直接使用开发者工具进行抓包,但有个局限,只能抓浏览器的,功能也没有多少.还可以 ...

  4. android 分享微信小程序失败,从一次失败的微信小程序抓包、反编译经历中学习反思...

    某天看到群里某个朋友说某小程序抓不到包,我突然就来了兴趣,我也试着分析了下这个小程序,名字我就不说了,本着我个人兴趣分析学习的目的. 我用安卓和IOS,以及charles和fiddler都试了,还真的 ...

  5. python 抓包解析数据_Python抓包并解析json爬虫的完整实例代码

    Python抓包并解析json爬虫 在使用Python爬虫的时候,通过抓包url,打开url可能会遇见以下类似网址,打开后会出现类似这样的界面,无法继续进行爬虫: 例如: 需要爬取网页中第二页的数据时 ...

  6. 使用Fiddler对IPhone手机的应用数据进行抓包分析

    原文出自: http://www.cr173.com/html/20064_1.html Fiddler能捕获ISO设备发出的请求,比如IPhone, IPad, MacBook. 等等苹果的设备.  ...

  7. 抓包,反抓包,反反抓包

    前言 当年还在学校的时候,就接触到了抓包,当时还在贴吧写了一篇小白文来误导小白(不是.但当时的自己还没接触到逆向,竟然对抓包没有提起兴趣,说到底又是太年轻,不懂事.时至今日,才发现它是安全人员必须要掌 ...

  8. Android安卓进阶之——一文带你了解抓包和反抓包

    今天主要跟大家介绍一下Android的抓包和防止抓包 介绍两款抓包工具,Profiter和Charles. 工具环境: Android Studio 4.2.2 手机Google Pixel 3XL ...

  9. api 数据 App 抓包工具 fiddler

    from   :  http://www.heyuan110.com/2015/06/17/App抓包工具fiddler/ App抓包工具fiddler Charles fiddler 抓包 确保安装 ...

最新文章

  1. ROW_NUMBER() OVER 函数的用法
  2. git push时提示:更新被拒绝,因为您当前分支的最新提交落后于其对应的远程分支
  3. memcached全面剖析 –3.memcached的删除机制和发展方向
  4. 执行sql语句_SQL查询语句的执行顺序解析
  5. python使用curve_fit拟合任意分布
  6. 【Java从0到架构师】SpringMVC - 特殊的请求参数
  7. 广义表取表头表尾_数据结构广义表的递归算法
  8. pythonchallenge之C++学习篇-01
  9. 工具栏的打印图标不见了_XP操作系统工具栏右边的打印机图标不见了
  10. 获取openwrt mac地址
  11. c语言calloc和malloc,使用malloc()、calloc()、free()和realloc()在C中进行动态内存分配
  12. XML Shema 笔记整理(1)
  13. matlab最基础教程(四):常用的系统自带函数,符号变量与字符串篇
  14. 从UAP-Studio中导出项目并且部署到服务器上
  15. 微信小程序API 文件·文件管理器
  16. html手机端下拉菜单代码,jQuery手机移动端下拉列表选择代码
  17. 进程与线程基础day02--------守护进程、系统日志、文件锁
  18. 量化交易之vnpy篇 - 几种同步发单模式(中金所股指锁仓模式、最小单边轧差操作模式、双边同步模式,净头寸模式)
  19. 新学问教育php,神墨教师的教育梦——让梦想与爱同行
  20. 数字 IC 设计、FPGA 设计秋招笔试题目、答案、解析(5)2021 华为海思(下)

热门文章

  1. #1.5与其它理论关系
  2. 2017第三十三届湖北(武汉)国际先进医疗仪器设备展览会会刊(参展商名录)
  3. 微信小程序开发 一 tabbar图标和颜色
  4. 基于单片机的自动化硬币分拣找零系统设计
  5. Android之最简单的Banner实现
  6. html++网页搜索框代码,CSS 漂亮搜索框美化代码
  7. 谱聚类(Spectral Clustering)1——算法原理
  8. ubuntu 迅雷 XwareDesktop
  9. verdi直接打开list文件
  10. 学习会计实操真的有用吗?