Dapper实现Like参数化
//参数直接写参数名 string Sql = "select * from [table] where field like @field"; //参数值里面加上通配符,varchar类型查询也不加单引号 var Param = new {field = "%{ParamValue}%"}; //执行查询 Dapper.Query<T>(Sql,Param); from:https://www.cnblogs.com/tian2008/p/8491633.html
View DetailsH5与App的通讯方式
前言 现在不管是桌面客户端还是移动客户端,都会夹杂着一部分H5页面,这种混合式的应用也是我们常说的Hybrid App。为什么会出现Hybrid App呢,早期是因为开发一个Android或iOS的客户端,需要的人力成本比较大,开发周期比较长,后来有些团队就通过将部分页面拆分出来,由前端来完成,再通过在客户端里的Webview来展示。 由于小编我半路转行当程序猿,只对前端领域有所了解,对其他编程领域接触较少,故不探讨Webview的实现原理和与H5页面交互的原理。有兴趣的小伙伴自行百度搜索JSBridge的相关知识,或请教下客户端(Windows、MacOS、Android、iOS)开发的同学,看看如何桥接JS与其他编程语言之间的联系。 优缺点 凡事都是有好有坏,没有绝对的解决方案。下面我总结下Hybrid App在开发过程中存在的优缺点,各位同学可自行判断Hybrid App的好坏。 优点 H5页面交由前端进行开发,页面模块之间分开开发和维护,有效减少App的开发周期 H5页面不受限于应用商店繁琐的审核流程和冗长的等待时间,新增页面和功能、修复缺陷都可随时部署到线上 H5页面在有需要时才加载,减小App打包后的大小,缩短App在应用商店下载的时间和减少本地占用手机的空间 H5页面接入App Webview中,不再受限于浏览器,可通过与App交互调用设备更多底层的API来完善更多原本浏览器无法完成的操作 缺点 协定好H5和App之间的通讯协议,定义好全局属性和全局方法在两者之间如何调用 H5页面接入App Webview中,可能会出现很多兼容问题,需要前端和客户端多加注意 开发前需按照需求和交互进行页面划分,哪些页面归前端开发,哪些页面归客户端开发 页面出现Bug有时候很难发现是在哪个环节出错,需要前端和客户端共同调试找出问题所在(可能各抒己见,打架都有份) 通讯方式 以下代码全部基于前端(React)进行演示,客户端如何实现JS交互我就不多说了,可以找客户端开发的同学了解下。通讯方式有如下两种,都是使用JS代码来完成,兼容性还是挺不错的。 前端通知客户端:拦截 客户端通知前端:注入 前端通知客户端 在H5页面里触发链接跳转,App Webview检测到链接跳转再进行拦截,因此可以通过URL上携带参数来告知App下一步应该做些什么。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import React, { Component } from "react"; export default class App extends Component { componentDidMount() { location.href = "lsbox://toast?msg=页面加载完毕"; // 通知App } render() { return ( <div className="app"> <button type="button" onClick={this.openMask.bind(this)}>点它</button> </app> ); } openMask() { location.href = "lsbox://mask?toggle=1"; // 通知App } } |
以上执行了location.href = "lsbox://mask?toggle=1"来通知App打开遮罩层 lsbox:前端和客户端统一定义链接跳转的协议(喜欢怎样定义协议都行) mask:App需要执行的动作(喜欢怎样定义动作都行) toggle=1:动作执行参数(自定义参数,用于告知App怎样做) 如果同步触发两个或以上的location.href(下一个location.href接着上一个location.href),App可能只会接收到一个location.href发出的通知,所以需要对下一个location.href使用setTimeout设置通知时间间隔(可使用Async/Await封装优化)
1 2 3 4 5 6 7 |
location.href = "lsbox://toast?msg=one"; setTimeout(() => { location.href = "lsbox://toast?msg=two"; setTimeout(() => { location.href = "lsbox://toast?msg=three"; }, 100); }, 100); |
客户端通知前端 注入一些全局方法,App Webview直接操作全局方法来控制H5页面,使用window.handleFunc = function() {}这样的形式来定义注入的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import React, { Component } from "react"; export default class App extends Component { constructor(props) { super(props); this.state = { list: [0, 1, 2, 3, 4] }; } componentDidMount() { window.addNum = this.addNum.bind(this); // 暴露方法给App } render() { return ( <div className="app"> <ul>{this.state.list.map(v => <li key={v}>{v}</li>)}</ul> </div>; ); } addNum(num) { this.setState(prevState => ({ list: prevState.list.concat(num); })); } } |
以上在组件加载完成后通过window.addNum = this.addNum.bind(this)将指定方法全局暴露到window上,App Webview可直接操作这些方法来控制H5页面。 作者:JowayYoung 链接:https://juejin.cn/post/6844904020201455624 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
View Details中高级前端必须注意的40条移动端H5坑位指南 | 网易三年实践
前言 不知不觉在网易已有三年半,占了一半时间都在与移动端打交道,整个阶段都是遇坑填坑的学习过程。移动端开发在前端里像神一样地存在,不是说它多难而是说它坑位实在太多了,怎样填都填不完。Android和iOS各显神通,Android的系统版本和屏幕分辨率多得难以一招兼容,iOS的顽固标准和未知特性多得难以快速掌握。 三年半沉淀通过本文记录下所遇到的坑位,或许有些坑位还未遇到,但本文记录的40条坑位绝对能让同学们少走很多弯路,特别是前端小白。为了减少废话提高本文质量,对以下内容做一些约定。 提及的安卓系统包括Android和基于Android开发的系统 提及的苹果系统包括iOS和iPadOS 本文针对的开发场景是移动端浏览器,因此大部分坑位的解决方案在桌面端浏览器里不一定有效 解决方案若未提及适用系统就默认在安卓系统和苹果系统上都适用,若提及适用系统则会详细说明 Webkit及其衍生内核在移动端浏览器市场占有率里达到惊人的97%,因此无需太过担心CSS3、ES6和浏览器新特性的兼容性 每次填坑都是一次实践过程,全部坑位的源码都按语言方向记录在笔者Github上,若有未记录的坑位可提PR让笔者合并,给个Star支持下咧! 本来想为每个坑位都截图或录播GIF作为演示,但考虑到目前掘金的Markdown编辑器操作图片还存在缺陷就放弃了,每次上传图片都会花费很多时间甚至上传失败(望掘金的产品小姐姐和程序小哥哥优化喔)。若需演示只能自行复制代码了。 HTML方向 调用系统功能 使用<a>能快速调用移动设备的电话/短信/邮件三大通讯功能,使用<input>能快速调用移动设备的的图库/文件。 这些功能方便了页面与系统的交互,关键在于调用格式一定要准确,否则会被移动端浏览器忽略。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!-- 拨打电话 --> <a href="tel:10086">拨打电话给10086小姐姐</a> <!-- 发送短信 --> <a href="sms:10086">发送短信给10086小姐姐</a> <!-- 发送邮件 --> <a href="mailto:young.joway@aliyun.com">发送邮件给JowayYoung</a> <!-- 选择照片或拍摄照片 --> <input type="file" accept="image/*"> <!-- 选择视频或拍摄视频 --> <input type="file" accept="video/*"> <!-- 多选文件 --> <input type="file" multiple> |
忽略自动识别 有些移动端浏览器会自动将数字字母符号识别为电话/邮箱并将其渲染成上述调用系统功能里的<a>。虽然很方便却有可能违背需求。
1 2 3 4 5 6 7 8 |
<!-- 忽略自动识别电话 --> <meta name="format-detection" content="telephone=no"> <!-- 忽略自动识别邮箱 --> <meta name="format-detection" content="email=no"> <!-- 忽略自动识别电话和邮箱 --> <meta name="format-detection" content="telephone=no, email=no"> |
弹出数字键盘 使用<input type="tel">弹起数字键盘会带上#和*,适合输入电话。推荐使用<input pattern="\d*">弹起数字键盘,适合输入验证码等纯数字格式。
1 2 3 4 5 |
<!-- 纯数字带#和* --> <input type="tel"> <!-- 纯数字 --> <input pattern="\d*"> |
唤醒原生应用 通过location.href与原生应用建立通讯渠道,这种页面与客户端的通讯方式称为URL Scheme,其基本格式为scheme://[path][?query],笔者曾经发表过《H5与App的通讯方式》讲述URL Scheme的使用。 scheme:应用标识,表示应用在系统里的唯一标识 path:应用行为,表示应用某个页面或功能 query:应用参数,表示应用页面或应用功能所需的条件参数 URL Scheme一般由前端与客户端共同协商。唤醒原生应用的前提是必须在移动设备里安装了该应用,有些移动端浏览器即使安装了该应用也无法唤醒原生应用,因为它认为URL Scheme是一种潜在的危险行为而禁用它,像Safari和微信浏览器。还好微信浏览器可开启白名单让URL Scheme有效。 若在页面引用第三方原生应用的URL Schema,可通过抓包第三方原生应用获取其URL。
1 2 3 4 5 6 7 8 9 10 11 |
<!-- 打开微信 --> <a href="weixin://">打开微信</a> <!-- 打开支付宝 --> <a href="alipays://">打开支付宝</a> <!-- 打开支付宝的扫一扫 --> <a href="alipays://platformapi/startapp?saId=10000007">打开支付宝的扫一扫</a> <!-- 打开支付宝的蚂蚁森林 --> <a href="alipays://platformapi/startapp?appId=60000002">打开支付宝的蚂蚁森林</a> |
禁止页面缩放 在智能手机的普及下,很多网站都具备桌面端和移动端两种浏览版本,因此无需双击缩放查看页面。禁止页面缩放可保障移动端浏览器能无遗漏地展现页面所有布局。
1 |
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, minimum-scale=1, maximum-scale=1"> |
禁止页面缓存 Cache-Control指定请求和响应遵循的缓存机制,不想使用浏览器缓存就禁止呗!
1 |
<meta http-equiv="Cache-Control" content="no-cache"> |
禁止字母大写 有时在输入框里输入文本会默认开启首字母大写纠正,就是输入首字母小写会被自动纠正成大写,特么的烦。直接声明autocapitalize=off关闭首字母大写功能和autocorrect=off关闭纠正功能。
1 |
<input autocapitalize="off" autocorrect="off"> |
针对Safari配置 贴一些Safari较零散且少用的配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<!-- 设置Safari全屏,在iOS7+无效 --> <meta name="apple-mobile-web-app-capable" content="yes"> <!-- 改变Safari状态栏样式,可选default/black/black-translucent,需在上述全屏模式下才有效 --> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <!-- 添加页面启动占位图 --> <link rel="apple-touch-startup-image" href="pig.jpg" media="(device-width: 375px)"> <!-- 保存网站到桌面时添加图标 --> <link rel="apple-touch-icon" sizes="76x76" href="pig.jpg"> <!-- 保存网站到桌面时添加图标且清除默认光泽 --> <link rel="apple-touch-icon-precomposed" href="pig.jpg"> |
针对其他浏览器配置 贴一些其他浏览器较零散且少用的配置,主要是常用的QQ浏览器、UC浏览器和360浏览器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<!-- 强制QQ浏览器竖屏 --> <meta name="x5-orientation" content="portrait"> <!-- 强制QQ浏览器全屏 --> <meta name="x5-fullscreen" content="true"> <!-- 开启QQ浏览器应用模式 --> <meta name="x5-page-mode" content="app"> <!-- 强制UC浏览器竖屏 --> <meta name="screen-orientation" content="portrait"> <!-- 强制UC浏览器全屏 --> <meta name="full-screen" content="yes"> <!-- 开启UC浏览器应用模式 --> <meta name="browsermode" content="application"> <!-- 开启360浏览器极速模式 --> <meta name="renderer" content="webkit"> |
让:active有效,让:hover无效 有些元素的:active可能会无效,而元素的:hover在点击后会一直处于点击状态,需点击其他位置才能解除点击状态。给<body>注册一个空的touchstart事件可将两种状态反转。
1 |
<body ontouchstart></body> |
CSS方向 自动适应布局 针对移动端,笔者通常会结合JS依据屏幕宽度与设计图宽度的比例动态声明<html>的font-size,以rem为长度单位声明所有节点的几何属性,这样就能做到大部分移动设备的页面兼容,兼容出入较大的地方再通过媒体查询做特别处理。 笔者通常将rem布局比例设置成1rem=100px,即在设计图上100px长度在CSS代码上使用1rem表示。
1 2 3 4 5 6 7 8 9 10 |
function AutoResponse(width = 750) { const target = document.documentElement; if (target.clientWidth >= 600) { target.style.fontSize = "80px"; } else { target.style.fontSize = target.clientWidth / width * 100 + "px"; } } AutoResponse(); window.addEventListener("resize", () => AutoResponse()); |
当然还可依据屏幕宽度与设计图宽度的比例使用calc()动态声明<html>的font-size,这样就能节省上述代码。不对,是完全代替上述代码。
1 2 3 |
html { font-size: calc(100vw / 7.5); } |
若以iPad Pro分辨率1024px为移动端和桌面端的断点,还可结合媒体查询做断点处理。1024px以下使用rem布局,否则不使用rem布局。
1 2 3 4 5 |
@media screen and (max-width: 1024px) { html { font-size: calc(100vw / 7.5); } } |
自动适应背景 使用rem布局声明一个元素背景,多数情况会将background-size声明为cover。可能在设计图对应分辨率的移动设备下,背景会完美贴合显示,但换到其他分辨率的移动设备下就会出现左右空出1px到npx的空隙。 此时将background-size声明为100% 100%,跟随width和height的变化而变化。反正width和height都是量好的实际尺寸。
1 2 3 4 5 |
.elem { width: 1rem; height: 1rem; background: url("pig.jpg") no-repeat center/100% 100%; } |
监听屏幕旋转 你还在使用JS判断横屏竖屏调整样式吗?那就真的Out了。
1 2 3 4 5 6 7 8 |
/* 竖屏 */ @media all and (orientation: portrait) { /* 自定义样式 */ } /* 横屏 */ @media all and (orientation: portrait) { /* 自定义样式 */ } |
[…]
View Details这些一行 JS 实现功能的代码,让你看起来像一个前端专家
JavaScript 可以做很多神奇的事情! 从复杂的框架到处理 API,有太多的东西需要学习。 但是,它也能让你只用一行代码就能做一些了不起的事情。 看看这 13 句 JavaScript 单行代码,会让你看起来像个专家! 1. 获取一个随机布尔值 (true/false) 这个函数使用 Math.random() 方法返回一个布尔值(true 或 false)。Math.random 将在 0 和 1 之间创建一个随机数,之后我们检查它是否高于或低于 0.5。这意味着得到真或假的几率是 50%/50%。
1 2 3 |
const randomBoolean = () => Math.random() >= 0.5; console.log(randomBoolean()); // Result: a 50/50 change on returning true of false |
2. 检查日期是否为工作日 使用这个方法,你就可以检查函数参数是工作日还是周末。
1 2 3 4 5 |
const isWeekday = (date) => date.getDay() % 6 !== 0; console.log(isWeekday(new Date(2021, 0, 11))); // Result: true (Monday) console.log(isWeekday(new Date(2021, 0, 10))); // Result: false (Sunday) |
3. 反转字符串 有几种不同的方法来反转一个字符串。以下代码是最简单的方式之一。
1 2 3 |
const reverse = str => str.split('').reverse().join(''); reverse('hello world'); // Result: 'dlrow olleh' |
4. 检查当前 Tab 页是否在前台 我们可以通过使用 document.hidden 属性来检查当前标签页是否在前台中。
1 2 3 |
const isBrowserTabInView = () => document.hidden; isBrowserTabInView(); // Result: returns true or false depending on if tab is in view / focus |
5. 检查数字是否为偶数 最简单的方式是通过使用模数运算符(%)来解决。如果你对它不太熟悉,这里是 Stack Overflow 上的一个很好的图解。
1 2 3 4 5 |
const isEven = num => num % 2 === 0; console.log(isEven(2)); // Result: true console.log(isEven(3)); // Result: false |
6. 从日期中获取时间 通过使用 toTimeString() 方法,在正确的位置对字符串进行切片,我们可以从提供的日期中获取时间或者当前时间。
1 2 3 4 5 |
const timeFromDate = date => date.toTimeString().slice(0, 8); console.log(timeFromDate(new Date(2021, 0, 10, 17, 30, 0))); // Result: "17:30:00" console.log(timeFromDate(new Date())); // Result: will log the current time |
7. 保留小数点(非四舍五入) 使用 Math.pow() 方法,我们可以将一个数字截断到某个小数点。
1 2 3 4 5 6 7 8 |
const toFixed = (n, fixed) => ~~(Math.pow(10, fixed) * n) / Math.pow(10, fixed); // Examples toFixed(25.198726354, 1); // 25.1 toFixed(25.198726354, 2); // 25.19 toFixed(25.198726354, 3); // 25.198 toFixed(25.198726354, 4); // 25.1987 toFixed(25.198726354, 5); // 25.19872 toFixed(25.198726354, 6); // 25.198726 |
8. 检查元素当前是否为聚焦状态 我们可以使用 document.activeElement 属性检查一个元素当前是否处于聚焦状态。
1 2 3 |
const elementIsInFocus = (el) => (el === document.activeElement); elementIsInFocus(anyElement) // Result: will return true if in focus, false if not in focus |
9. 检查浏览器是否支持触摸事件
1 2 3 4 5 |
const touchSupported = () => { ('ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch); } console.log(touchSupported()); // Result: will return true if touch events are supported, false if not |
10. 检查当前用户是否为苹果设备 我们可以使用 navigator.platform 来检查当前用户是否为苹果设备。
1 2 3 |
const isAppleDevice = /Mac|iPod|iPhone|iPad/.test(navigator.platform); console.log(isAppleDevice); // Result: will return true if user is on an Apple device |
11. 滚动到页面顶部 […]
View Details命名秘籍周获近五千星——GitHub 热点速览 v.21.04
作者:HelloGitHub-小鱼干 命名一直是编程界的难点,这次 naming-cheatsheet 就能帮上你的忙。按照它的 SID(Short.、Intuitive、Descriptive)原则,你一定能取出极佳的变量 / 函数名。同样,能解决你可视化问题的还有 Apache 的 superset。如果你想了解 Google、微软、Netflix 之类的大厂在生产环境应用了哪些机器学习技术,applied-ml 就能娓娓道来各大科技公司的 ml 技术。 这期依旧是小鱼干自由发挥的一期热点趋势,和原来一样如果你想了解特定主题的 GitHub Repo,小鱼干定会留意这周的 GitHub Trending。 以下内容摘录自微博@HelloGitHub 的 GitHub Trending 及 Hacker News 热帖(简称 HN 热帖),选项标准:新发布 | 实用 | 有趣,根据项目 release 时间分类,发布时间不超过 14 day 的项目会标注 New,无该标志则说明项目 release 超过半月。由于本文篇幅有限,还有部分项目未能在本文展示,望周知 🌝 本文目录 本周特推 1.1 命名秘籍:naming-cheatsheet 1.2 机器学习库:best-of-ml-python GitHub Trending 周榜 2.1 免费编程书籍:free-programming-books 2.2 大厂的技术实践:applied-ml 2.3 新的编译方式:Svelte 2.4 可视化工具:superset 2.5 模拟数据:faker.js 2.6 角色扮演:ActionRoguelike 往期回顾 1. 本周特推 1.1 命名秘籍:naming-cheatsheet 本周 star 增长数:4,900+ naming-cheatsheet 是一个两年之前的项目,这周焕发了新生一周获得了近 5k star。本项目旨在帮你解决命名困难的问题,教你如何便捷、轻松地进行命名。命名谨记以下三点(SID): 短:一个名字一定不要花很长的时间来键入,因此,记住; 直观:一个名字必须读起来自然,尽可能接近日常用语; 描述性:一个名字必须以最有效的方式反映它所做 / 拥有的东西。 GitHub 地址→github.com/kettanaito/… 1.2 机器学习库:best-of-ml-python 本周 star 增长数:2,750+ […]
View DetailsNaming cheatsheet
Naming things is hard. This sheet attempts to make it easier. Although these suggestions can be applied to any programming language, I will use JavaScript to illustrate them in practice. English language Use English language when naming your variables and functions.
1 2 3 4 5 6 7 |
/* Bad */ const primerNombre = 'Gustavo' const amigos = ['Kate', 'John'] /* Good */ const firstName = 'Gustavo' const friends = ['Kate', 'John'] |
Like it or not, English is the dominant language in programming: the syntax of all programming languages is written in English, as well as countless documentations and educational materials. By writing your code in English you dramatically increase its cohesiveness. Naming convention Pick one naming convention and […]
View DetailsBlockquote
Blockquote 对象 Blockquote 对象代表着一个 HTML 引用(blockquote)块元素。 <blockquote> 标签定义摘自另一个源的块引用。 一个 <blockquote> 元素的内容通常展现为一个左、右两边进行缩进的段落。 在 HTML 文档中的每一个 <blockquote> 标签创建时,都会创建一个 Blockquote 对象。 from:
View Details阻止IIS应用程序池自动回收
在IIS中找到这个站点所用的程序池,点击“高级设置…” 在打开的列表中更改以下设置: 回收 固定时间间隔(分钟) 改为 0 虚拟/专用内存限制(KB) 改为 0 进程模型 闲置超时(分钟) 改为 0 from:bubuko.com/infodetail-1708029.html
View DetailsWeb 防爬指南
(或至少让其更难抓取) 这篇文章我翻译自:https://github.com/JonasCz/How-To-Prevent-Scraping,因为最近在看一些反爬的资料,无意间在 Github 发现这篇文章,我觉得写的很全面,所以想要翻译一下,顺便进行吸收。另外让我觉得非常赞的是这个文章从服务端和前端的角度都做了分析,我们应该从哪些点去做优化,而且每个点都举了例子,有些还给出了注意点。虽然文中有些提到的一些点很基础,也有很多我们目前在业务中也在使用,但是我还是从中吸收到了一些新东西,里面文中外部链接有很多,但是公众号这里不允许外链,所以大家可以点击文末最后的"阅读原文"到 Github 去查看,Github Markdown 的排版可能也比这里更好 : )。 (最后,有些仓促,可能有些注意不到的措别字,还请多多包涵) 提示:这篇文章是我 Stack Overflow 这个问题回答的扩展,我把它整理在 Github 因为它实在是太长了,超过了 Stack Overflow 的字数限制(最多 3 万个字,这文章已经超过 4 万字) 欢迎大家修改、完善还有分享,本文使用 CC-BY-SA 3.0 许可。 本质上说,防抓的目的在于增加脚本或机器获取你网站内容的难度,而不要影响真实用户的使用或搜索引擎的收录 不幸的是这挺难的,你需要在防抓和降低真实用户以及搜索引擎的可访问性之间做一下权衡。 为了防爬(也称为网页抓取、屏幕抓取、网站数据挖掘、网站收割或者网站数据获取),了解他们的工作原理很重要,这能防止他们能高效爬取,这个就是这篇文章的主要内容。 通常情况下,抓取程序的目的是为了获取你网站特定的信息,比如文章内容、搜索结果、产品详情还有网站上艺术家或者相册信息。他们爬取这些内容用于维护他们自己的网站(甚至通过你的内容赚钱!),或者制作和你网站不一样的前端界面(比如去做移动 APP),还有一些可能作为个人研究或分析使用。 实际上,有特别多的爬虫类型,而且他们的爬取方式都不太相同: 蜘蛛,比如 Google’s bot 或者网站复制工具 HTtrack,他们访问你的网站,而且在页面中寻找链接后递归的去爬取以获取页面的数据。有时候他们只用于获取特定数据,而不会全部爬取,通常结合 HTML 分析器在页面中获取想要的数据。 Shell 脚本,有时候,通用的 Unix 工具也被用来爬取:wget 或者 curl 用于下载页面,用 Grep (Regex) 去分析获取想要的数据,一般都会写一个 Shell 脚本。这些都是最简单的爬虫,也是最脆弱的一类爬虫(Don’t ever try parse HTML with regex !),所以是最早发现和防范的爬虫。 HTML 爬取器和分析器,会基于 Jsoup、Scrapy 还有其他一些工具。和 shell 脚本基于正则类似,他们呢基于特定模式(pattern)分析你的 HTML 结构从而获取想要的数据。 举个例子:如果你的网站有搜索功能,那这个爬虫可能会模拟提交一个搜索的 HTTP 请求,然后从搜索结果页中获取所有的链接和标题,有时候会构造有成千上百不同的请求,只是为了获取标题和链接而已。这是最常见的一类爬虫。 屏幕爬取,比如会基于 Selenium 或者 PhantomJS,他们实际上会通过真实浏览器打开你的网站,因此也会运行你网站的 JavaScript、AJAX 或者其他的,然后他们从你的页面获取自己想要的文本内容,通常: 基于浏览器的爬取很难处理,他们运行脚本,渲染 HTML,就像真实用户一样访问你的网站。 等页面加载完毕, JavaScript 也执行之后,从浏览器获取 HTML 结构,然后用 HTML 分析器去获取想要的数据或者文本。这是常见做法,所以有很多方法可以防止这类 HTML 分析器或爬虫。 […]
View DetailsMySQL 查询优化
索引 索引是什么 MySQL 官方对索引的定义为:索引(Index)是帮助 MySQL 高效获取数据的数据结构。可以得到索引的本质:索引是数据结构。 可以简单理解为排好序的快速查找数据结构。 在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。 一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。 优缺点 优点 提高数据检索的效率,降低数据库的 IO 成本。 通过索引列对数据进行排序,降低数据排序的成本,降低了 CPU 的消耗。 缺点 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行 INSERT、UPDATE 和 DELETE。因为更新表时,MySQL 不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为 更新所带来的键值变化后的索引信息。 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间 的。 B-Tree 和 B+Tree 区别 B-Tree 的关键字和记录是放在一起的,叶子节点可以看作外部节点,不包含任何信息;B+Tree 的非叶子节点中只有关键字和指向下一个节点的索引,记录只放在叶子节点中。 在 B-Tree 中,越靠近根节点的记录查找时间越快,只要找到关键字即可确定记录的存在;而 B+Tree 中每个记录的查找时间基本是一样的,都需要从根节点走到叶子节点,而且在叶子节点中还要再比较关键字。从这个角度看 B-Tree 的性能好像要比 B+Tree 好,而在实际应用中却是 B+Tree 的性能要好些。因为 B+Tree 的非叶子节点不存放实际的数据,这样每个节点可容纳的元素个数比 B-Tree 多,树高比 B-Tree 小,这样带来的好处是减少磁盘访问次数。尽管 B+Tree 找到一个记录所需的比较次数要比 B-Tree 多,但是一次磁盘访问的时间相当于成百上千次内存比较的时间,因此实际中 B+Tree 的性能可能还会好些,而且 B+Tree 的叶子节点使用指针连接在一起,方便顺序遍历(例如查看一个目录下的所有文件,一个表中的所有记录等),这也是很多数据库和文件系统使用 B+Tree 的缘故。 为什么 B+Tree 比 B-Tree 更适合实际应用中操作系统的文件索引和数据库索引? B+Tree 的磁盘读写代价更低 B+Tree 的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对 B-Tree 更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说 IO 读写次数也就降低了。 B+Tree 的查询效率更加稳定 由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。 索引分类 单值索引:即一个索引只包含单个列,一个表可以有多个单列索引 建表时,加上 key(列名) 指定 单独创建,create index 索引名 on 表名(列名) 单独创建,alter table […]
View Details