
熟悉MySQL,SQL Server等数据库,熟悉.NET和Java相关领域, 擅长.NET ,PHP,Python,Node.js,SQL Server,jQuery 喜欢音乐和诗歌的技术宅
我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。
彻底解决mysql中文乱码 mysql是我们项目中非经常常使用的数据型数据库。 可是由于我们须要在数据库保存中文字符,所以经常遇到数据库乱码情况。以下就来介绍一下怎样彻底解决数据库中文乱码情况。 数据库执行 SHOW VARIABLES LIKE '%char%' 看到字符集都是latin1 创建数据库及表时设置字符集,避免出现中文乱码的方法: 创建数据库 CREATE DATABASE test CHARACTER SET utf8 COLLATE utf8_general_ci; --注意后面三个单词之间是有下划线的对于每个选项所给定的值,前面没有等号;在第一个选项和第二个选项之间也没有逗号。 创建表 CREATE TABLE cartoon( name varchar(20), sex varchar(20), age varchar(20), country varchar(20) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 这几个设置好了,基本就不会出问题。 INSERT INTO `cartoon` VALUES('校长','男','54','中国'); 设置MySQL的my.ini文件 分别在[client] 标签和 [mysqld] 添加:character_set_server=utf8
PHP中关于时间(戳)、时区、本地时间、UTC时间等的梳理 在PHP开发中,我们经常会在时间问题上被搞糊涂,比如我们希望显示一个北京时间,但是当我们使用date函数进行输出时,却发现少了8个小时。几乎所有的php猿类都必须对php中几个重要的时间转换等方法进行研究。本文就来梳理这些问题。 时间戳(timestamp) GMT 在时间戳这个点上,它是一个概念,而不是具体的编程问题,是计算机世界通用的一种约定。时间戳是指格林尼治时间(GMT)1970年01月01日00时00分00秒到当前时间的总秒数。 GMT(也被称为世界时)是固定为本初子午线经过地区的时间,因此被作为时间参照物。 UTC 协调世界时(UTC)和GMT一样都是一种时间的参照物,但是他们的计算方法不同UTC是以原子时秒长为基础,在时刻上尽量接近于世界时的一种时间计量系统,从精度上讲,更加精确(自然也比GMT更精确),因此被称世界统一时间,世界标准时间,国际协调时间。 Unix时间戳 Unix时间戳是在计算机领域才有的,每一台电脑(服务器)在生产的时候,将GMT/UTC的1970年01月01日00时00分00秒作为起始值进行计算,得到的总秒数就是这个Unix时间戳。至于是GMT还是UTC意义并不大,因为GMT和UTC的1970年01月01日00时00分00秒是一致的,起点一致的情况下,运行的秒数也是一致的。 为什么要时间戳?因为从0开始运行的秒数永远相等,即使出现润秒,也并不影响时间戳。在php中,可以通过time函数获取时间戳: time(); 但是你应该明白,time()获取的是,当前这台电脑(服务器)上的Unix时间戳。两台电脑可能这个时间戳并不相同,有的甚至相差几十秒。从理论上讲时间戳应该是一摸一样的,但是由于不同的电脑硬件出厂时的设定不同,也会导致GMT/UTC起始值稍有差异,甚至在计算每一秒时也有可能存在差异,这台机器上一秒的时间比另一台要长也是有可能的,时间久了,积累下来的时间差就会体现出来。但是,这种时间差一般不会超过几秒钟。 时区(Time Zone) 但是上面的time()的表述并不准确,因为我们在实践中经常遇到time()得到的值并不是我们想要的。对应的是,date()函数得到的值,也可能出乎我们意料。 什么是时区呢?也就是以GMT/UTC为参照物的时间偏移。 以GMT为参照物的时区 在传统的教材里,全球被划分为24个时区,首先基于经度,其次按照国家或地区,将每一个地区划分到某一个时区,这样可以避免时间上的混乱。在24时区划分之前,世界上的时间换算并没有准确的参照,比如中国人去英国,只能问当地人现在几点,然后拨自己的表来对。而当时区划分之后,中国人到了英国,只需要拨慢8小时即可。在时区划分之前,英国人跟中国人的时间可能并不是严格的8小时之差。 但为了照顾到同一个国家内时间的统一,大部分国家规定自己属于同一个时区,比如中国,统一规定为东八区,这样中国东部和西部可以采用同一个时间。毕竟没有必要大家一定要在早上6点看到日出,沿海城市5点看,乌鲁木齐9点看,并不影响大家的正常作息。 在php中,提供了大量的地区作为时区切换的标准,例如: date_default_timezone_set('Asia/Shanghai');echo date('Y-m-d H:i:s'); // 获得的是上海所在时区的时间 注意:PRC是中国的地区时标志,并不在Asia中,而是在Others里面找。 以UTC为参照物计算时区 但随着UTC取代GMT成为世界标准时后,时区的计算开始使用UTC作为标准。UTC+8代表东八区,UTC-11代表西十一区。不过随着精度需求的提升,按大时区计算已经不能满足需求,0.5个时区也被普遍使用,比如UTC+7.5。 在PHP中,我们可以采用这种方式来切换时区。比如: date_default_timezone_set('UTC');echo date('Y-m-d H:i:s'); // 获取的是0时区时间php测试代码:time.php <?php //设置时区 echo '<br/>默认时区时间:'.date("Y-m-d H:i:s").'<br/>'; //可以在文件开头位置设置默认配置的时区 //也可以在php.ini中进行设置date.timezone(所有文件生效) ini_set('date.timezone','Asia/Shanghai'); echo '<br/>上海时区时间:'.date("Y-m-d H:i:s").'<br/>'; //或者直接设置时间格式 date_default_timezone_set('asia/tokyo'); echo '<br/>东京时区时间:'.date("Y-m-d H:i:s").'<br/>'; echo '<br/>格式化时间:'.date("YmdHis").'<br/>'; ?> 输出: 默认时区时间:2018-09-15 10:53:06 上海时区时间:2018-09-15 16:53:06 东京时区时间:2018-09-15 17:53:06 格式化时间:20180915175306 摘自:https://www.tangshuang.net/2794.html
EventProxy流程控制 EventProxy是一个通过控制事件触发顺序来控制业务流程的工具。 1. 利用事件机制解耦复杂业务逻辑2. 移除被广为诟病的深度callback嵌套问题3. 将串行等待变成并行等待,提升多异步协作场景下的执行效率4. 友好的Error handling node.js的亮点是回调函数,node.js流程控制、传参都是通过回调函数来实现的。开发中经常会遇到回调嵌套的场景,尤其是在业务复杂的场景下,会嵌套n层回调函数,这样做的原因是为了控制代码执行的流程。 下面是一个需要同步读取文件的例子 var str = ''; fs.readFile('file1.txt', function(err, data1) { str += data1; fs.readFile('file2.txt', function(err, data2) { str += data2; fs.readFile('file3.txt', function(err, data3) { str += data3; }); }); }); 上面代码有3层回调嵌套,用嵌套来保障文件的顺序读取。这样代码可读性就比较差了,而开发中用到的嵌套往往有很多层,代码很难读。 我们用EventProxy来解耦 安装:npm install eventproxy 引包:var EventProxy = require('eventproxy'); var ep = new EventProxy(); 1、异步协作 all 多个操作并行执行,每个操作完成后触发一个自定义事件.ep.all监听所有操作触发的事件,然后在回调函数里面提供各事件提供的结果 ep.all('read1', 'read2', 'read3', function(data1, data2, data3) { //监听事件,所有事件都触发完成后,在这里汇总结果 console.info(data1 + '~' + data2 + '~' + data3); }); fs.readFile('file1.txt', function(err, data1) { ep.emit('read1', data1);//触发事件 }); fs.readFile('file2.txt', function(err, data2) { ep.emit('read2', data2);//触发事件 }); fs.readFile('file3.txt', function(err, data3) { ep.emit('read3', data3);//触发事件 }); 2、重复异步协作 after `after`方法适合重复的操作,比如读取10个文件,调用5次数据库等。将handler注册到N次相同事件的触发上。达到指定的触发数,handler将会被调用执行,每次触发的数据,将会按触发顺序,存为数组作为参数传入。 var files = ['file1.txt', 'file2.txt', 'file3.txt']; ep.after('readfile', files.length, function(list) { // 在所有文件的异步执行结束后将被执行 // 所有文件的内容都存在list数组中 //list中值是无序的,因为for循环中ep.emit触发顺序是无序的(node异步特点),排列顺序取决于node事件触发的顺序。可以通过group来控制对应关系,后续讲。 }); for (var i = 0; i < files.length; i++) { fs.readFile(files[i], function(err, data) { // 触发结果事件 ep.emit('readfile', data); }); } 注意:如果ep.emit('你的事件名称') 的次数没有达到after中次数(第二个参数),是无法触发after的回调函数的,这里一定要注意! 参考:https://blog.csdn.net/shmnh/article/details/43866677
简单的node爬虫练手,循环中的异步转同步 转载:https://blog.csdn.net/qq_24504525/article/details/77856989 看到网上一些基于node做的爬虫项目,自己也想写一下练手,正好同事需要各省市的信息一、开发环境搭建 node 安装最新版 后面会用到async、await webstrom编辑器 新建reptitle文件夹 --> npm init (初始化工程) 二、爬取页面分析 入口 ,获取该页面所有的省市,记录下省市名称,及html地址 查询省市下面的市区 依次爬取,略。。 三、关键代码 1. 代码分析 cheerio包用于解析页面中的html,用法同jquery fs 生成文件 http 发起get请求页面 async 用于解决异步 iconv、bufferhelper 用于解析中文乱码 2. 因为http发起的请求是异步,循环中的异步函数不能按照想要的既定顺序执行,所以我用es6、7中的promise async await 将异步函数转化成同步 3. 代码 let http = require("http"); let cheerio = require("cheerio"); let fs = require("fs"); let async = require("async"); let iconv = require('iconv-lite'); let BufferHelper = require('bufferhelper'); let initUrl = "http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/index.html"; let url = "http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/";//初始url let dataSource = []; /** * @method 生成文件 * @param fileName * @param text */ const createTxt =(fileName,text) =>{ return new Promise((resolve,reject)=>{ fs.appendFile("spider/data/"+fileName+".txt",text,"utf-8",function(err){ if(err){ console.log(err) }else{ resolve(true) } }) }) }; /** * @method promise封装http请求 * @returns {Promise.<void>} */ const httpGet = (url) =>{ return new Promise((resolve,reject)=>{ http.get(url,(res)=>{ let buffer = new BufferHelper(); res.on("data",(data)=>{ buffer.concat(data); }); res.on("end",()=>{ let buf = buffer.toBuffer(); let html = iconv.decode(buf,'GBK'); let $ = cheerio.load(html); //采用cheerio解析页面 resolve($); }) }) }) }; /** * @method 获取所有省 * @param initUrl * @returns {Promise.<void>} */ async function getProvince(initUrl) { console.time("计时器"); let subUrlArray = []; await httpGet(initUrl).then(($)=>{ let provincetds = $(".provincetr td"); provincetds.each((i)=> { let subUrl = provincetds.eq(i).find("a").attr("href"); let name = provincetds.eq(i).find("a").text(); dataSource.push({ province: name, cityArray: [] }); //将函数参数放入队列 subUrlArray.push({ url: url, subUrl: subUrl, j: i }); }) }); //await的上下文async // console.log(subUrlArray) for(let i=0;i<subUrlArray.length;i++){ console.log("进入"+dataSource[i].province); await startRequest(url,subUrlArray[i].subUrl,i); //根据省生成文件 let fileName = dataSource[i].province; let text = JSON.stringify(dataSource[i].cityArray); await createTxt(fileName,text); } console.timeEnd("计时器"); } /** * @method 根据省查询该省下面的所有市 * @param url * @param subUrl * @param i * @returns {Promise} */ async function startRequest(url,subUrl,i){ let subUrlArray = []; await httpGet(url+subUrl).then(($)=>{ let citytr = $(".citytr"); //保存省市和地址 citytr.each(function(index){ let cityNum = $(this).find("td").eq(0).find("a").text(); let name = $(this).find("td").eq(1).find("a").text(); let cityUrl = $(this).find("td").eq(0).find("a").attr("href"); dataSource[i]["cityArray"].push({ city : name, cityNum : cityNum, countryArray : [] }); //将函数参数放入队列 let countryUrl = url.replace(/.html/,""); subUrlArray.push({ countryUrl: countryUrl, subUrl: cityUrl, }); }); }); for(let j=0;j<subUrlArray.length;j++){ let url = subUrlArray[j].countryUrl; let subUrl = subUrlArray[j].subUrl; await startCounty(url,subUrl,i,j); } } /** * @method 查询市区下面的区县 * @param url * @param subUrl * @param proIndex * @param cityIndex * @returns {Promise.<void>} */ async function startCounty(url,subUrl,proIndex,cityIndex){ let subUrlArray = []; //console.log("进入区县",url+subUrl) await httpGet(url+subUrl).then(($)=>{ let countytr = $(".countytr"); //保存区县和地址 countytr.each(function(i){ //console.log("区县",i) let countyNum = $(this).find("td").eq(0).find("a").text(); let name = $(this).find("td").eq(1).find("a").text(); let areaurl = $(this).find("td").eq(0).find("a").attr("href"); dataSource[proIndex]["cityArray"][cityIndex]["countryArray"].push({ county : name, countyNum : countyNum, areaArray : [], }); let newUrl = subUrl.split(/\//)[0]+"/"+areaurl; if(areaurl){ subUrlArray.push({ newUrl : newUrl, index : i }); } }); }); for(let i=0;i<subUrlArray.length;i++){ let data = subUrlArray[i]; await getTree(url,data.newUrl,proIndex,cityIndex,data.index); } } /** * @method 根据区县爬取街道 * @param url * @param subUrl * @param proIndex * @param cityIndex * @param countyIndex * @returns {Promise.<void>} */ async function getTree(url,subUrl,proIndex,cityIndex,countyIndex){ let subUrlArray = []; //console.log("街道",url+subUrl) await httpGet(url+subUrl).then(($)=>{ let towntr = $(".towntr"); //console.log("towntr",towntr.length) //保存区县和地址 towntr.each(function(i){ let countyNum = $(this).find("td").eq(0).find("a").text(); let name = $(this).find("td").eq(1).find("a").text(); let newurl = $(this).find("td").eq(0).find("a").attr("href"); dataSource[proIndex]["cityArray"][cityIndex]["countryArray"][countyIndex]["areaArray"].push({ area : name, areaNum : countyNum, jwhArray : [], }); let reUrl = subUrl.split(/\//)[0]+"/"+subUrl.split(/\//)[1]+"/"+newurl; if(newurl){ subUrlArray.push({ reUrl : reUrl, index : i }) } }); }); for(let i=0;i<subUrlArray.length;i++){ let data = subUrlArray[i]; await getJwh(url,data.reUrl,proIndex,cityIndex,countyIndex,data.index); } } /** * @method 根据街道爬取办事处 * @param url * @param subUrl * @param proIndex * @param cityIndex * @param countyIndex * @param areaIndex * @returns {Promise.<void>} */ async function getJwh(url,subUrl,proIndex,cityIndex,countyIndex,areaIndex){ let subUrlArray = []; //console.log("getJwh",url+subUrl); await httpGet(url+subUrl).then(($)=>{ let villagetr = $(".villagetr"); //console.log(villagetr.length); villagetr.each(function(i){ let countyNum = $(this).find("td").eq(0).text(); let name = $(this).find("td").eq(2).text(); dataSource[proIndex]["cityArray"][cityIndex]["countryArray"][countyIndex]["areaArray"][areaIndex]["jwhArray"].push({ jwh : name, jwhNum : countyNum, }); //console.log("name",name) }); }) } getProvince(initUrl);