微信公众号开发模型WeChat
模型:WeChat (回复参考weiphp)
<?php
namespace Org;
/**
* 微信开发工具类
* Class WeChat
* Author chenqionghe
* @package Org
*/
class WeChat
{
const LOG_NAME = "PHP_LOG_%s.log.php"; //日志名
const LOG_DIR = "./Log/%s/"; //日志目录 static private $fromUser = ''; //当前消息的发送者
static private $toUser = ''; //当前消息的接收者
static private $member = ''; //公众号会员记录 /**
* 设置要操作的微信公众号
* @param $mid 公众号id
*/
static public function setMember($mid)
{
self::$member = M('Member')->find($mid);
}
/**
* 处理来自微信服务器的消息
* @param $callback
* @access public
* @return void
*/
static public function process($callback)
{
//如果回调函数没有设置,则退出
if (!is_callable($callback))
{
return;
}
$postData = $GLOBALS['HTTP_RAW_POST_DATA'];
if (empty($postData)) return; //如果没有POST数据,则退出
$object = simplexml_load_string($postData, 'SimpleXMLElement', LIBXML_NOCDATA);//解析POST数据(XML格式)
$messgeType = trim($object->MsgType); //取得消息类型
self::$fromUser = $object->FromUserName; //记录消息发送方(不是发送者的微信号,而是一个加密后的OpenID)
self::$toUser = $object->ToUserName; //记录消息接收方(就是公共平台的OpenID)
self::addLog($postData,1,$messgeType); //记录日志 //根据不同的消息类型,分别处理
switch($messgeType)
{
case "text": //文本消息
//调用回调函数
call_user_func($callback, "Text", array('Content'=>$object->Content));
break;
case "image": //图片消息
call_user_func($callback, "Image",array('PicUrl'=>$object->PicUrl, 'MediaId'=>$object->MediaId));
break;
case "voice": //音频消息
call_user_func($callback, "Voice",array('MediaId'=>$object->MediaId, 'Format'=>$object->Format,'Recognition'=>$object->Recognition) );
break;
case "video": //视频消息
call_user_func($callback, "Video", array('MediaId'=>$object->MediaId, 'ThumbMediaId'=>$object->ThumbMediaId));
break;
case "shortvideo": //小视频消息
call_user_func($callback, "Shortvideo", array('MediaId'=>$object->MediaId, 'ThumbMediaId'=>$object->ThumbMediaId));
break;
case "location": //定位信息
call_user_func($callback, "Location", array('Label'=>$object->Label, 'Location_X'=>$object->Location_X, 'Location_Y'=>$object->Location_Y,'Scale'=>$object->Scale));
break;
case "link": //链接信息
call_user_func($callback, "Link", array('Url'=>$object->Url, 'Title'=>$object->Title, 'Description'=>$object->Description));
break;
case "event": //事件
switch ($object->Event)
{
case "subscribe": //订阅事件
call_user_func($callback, "Subscribe",array( 'EventKey'=>$object->EventKey, 'Ticket'=>$object->Ticket));
break;
case "unsubscribe": //取消订阅事件
call_user_func($callback, "UnSubscribe", array('FromUserName'=>$object->FromUserName));
break;
case "CLICK": //点击菜单拉取消息时的事件
call_user_func($callback, "Click", array('EventKey'=>$object->EventKey));
break;
case "VIEW": //点击菜单跳转链接时的事件
call_user_func($callback, "View",array('EventKey'=> $object->EventKey));
break;
case "scancode_push": //扫码推事件的事件推送
call_user_func($callback, "ScanPush",array( 'EventKey'=>$object->EventKey,'ScanCodeInfo'=>$object->ScanCodeInfo,'ScanType'=>$object->ScanType,'ScanResult'=>$object->ScanResult));
break;
case "scancode_waitmsg": //扫码推事件且弹出“消息接收中”提示框的事件推送
call_user_func($callback, "ScanWaitmsg",array( 'EventKey'=>$object->EventKey,'ScanCodeInfo'=>$object->ScanCodeInfo,'ScanType'=>$object->ScanType,'ScanResult'=>$object->ScanResult));
break;
case "pic_sysphoto": //弹出系统拍照发图的事件推送
call_user_func($callback, "PicSysPhoto",array( 'EventKey'=>$object->EventKey, 'SendPicsInfo'=>$object->SendPicsInfo,'Count'=>$object->Count,'PicList'=>$object->PicList,'PicMd5Sum'=>$object->PicMd5Sum));
break;
case "pic_photo_or_album": //弹出拍照或者相册发图的事件推送
call_user_func($callback, "PicPhotoOrAlbum",array( 'EventKey'=>$object->EventKey, 'SendPicsInfo'=>$object->SendPicsInfo,'Count'=>$object->Count,'PicList'=>$object->PicList,'PicMd5Sum'=>$object->PicMd5Sum));
break;
case "pic_weixin": //弹出微信相册发图器的事件推送
call_user_func($callback, "PicWeixin",array( 'EventKey'=>$object->EventKey, 'SendPicsInfo'=>$object->SendPicsInfo,'Count'=>$object->Count,'PicList'=>$object->PicList,'PicMd5Sum'=>$object->PicMd5Sum));
break;
case "location_select": //弹出地理位置选择器的事件推送
call_user_func($callback, "LocationSelect",array( 'EventKey'=>$object->EventKey, 'SendLocationInfo'=>$object->SendLocationInfo,'Location_X'=>$object->Location_X,'Location_Y'=>$object->Location_Y,'Scale'=>$object->Scale,'Label'=>$object->Label,'Poiname'=>$object->Poiname));
break;
case 'LOCATION': //上报地址位置事件
call_user_func($callback, "UpLocation",array( 'Latitude'=>$object->Latitude, 'Longitude'=>$object->Longitude, 'Precision'=>$object->Precision));
break;
default :
//Unknow Event
break;
}
break;
default:
//未知消息类型
break;
}
} /**
* 获取access_token
* $mid 公众号id
* @access public
* @return mixed
*/
static public function getAcctoken ($mid='')
{
if(empty($mid)) {
$mid = defined('MID') ? MID : session('mid'); //如果定义了常量MID说明是微信请求的 ,否则是本地
}
$token = S('access_token'.$mid);
if ($token === false)
{
if(empty(self::$member)) {
self::$member = M('Member')->find($mid);
}
$url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.self::$member['appid'].'&secret='.self::$member['secret'];
$result = self::http_get($url);
$result = json_decode($result, true);
$token = $result['access_token'];
S('access_token'.$mid, $token, $result['expires_in'] - 1000);
}
return $token;
} /**
* 验证签名是否正确
* @access public
* @param $token
*/
static public function checkSignature($token)
{
$tmpArr = array($token,$_GET ["timestamp"],$_GET ["nonce"]);
sort($tmpArr, SORT_STRING );
$tmpStr = sha1(implode( $tmpArr));
if ($tmpStr == $_GET ["signature"])
{
ob_clean();
echo $_GET ["echostr"];
}
self::addLog($_GET,4,'微信接入');//记录日志
exit;
} /*************************************************** 发送消息响应微信 begin ***************************************************/
/**
* 回复文本消息
* @param $content 文本内容
* @access public
* @return void
*/
static public function replyText($content)
{
$msg ['Content'] = $content;
self::_replyData ( $msg, 'text' );
} /**
* 回复图片消息
* @param $media_id MediaId
*/
static public function replyImage($media_id)
{
$msg ['Image'] ['MediaId'] = $media_id;
self::_replyData ( $msg, 'image' );
} /**
* 回复语音消息
* @param $media_id MediaId
* @access public
* @return void
*/
static public function replyVoice($media_id)
{
$msg ['Voice'] ['MediaId'] = $media_id;
$msg ['Voice'] ['MediaId'] = $media_id;
self::_replyData ( $msg, 'voice' );
} /**
* 回复视频消息
* @param $media_id MediaId
* @param string $title 标题
* @param string $description 简介
* @access public
* @return void
*/
static public function replyVideo($media_id, $title = '', $description = '')
{
$msg ['Video'] ['MediaId'] = $media_id;
$msg ['Video'] ['Title'] = $title;
$msg ['Video'] ['Description'] = $description;
self::_replyData ( $msg, 'video' );
} /**
* 回复音乐消息
* @param $media_id MediaId
* @param string $title 标题
* @param string $description 简介
* @param $music_url 音乐地址
* @param $HQ_music_url 高品质音乐地址
* @access public
* @return void
*/
static function replyMusic($media_id, $title = '', $description = '', $music_url, $HQ_music_url)
{
$msg ['Music'] ['ThumbMediaId'] = $media_id;
$msg ['Music'] ['Title'] = $title;
$msg ['Music'] ['Description'] = $description;
$msg ['Music'] ['MusicURL'] = $music_url;
$msg ['Music'] ['HQMusicUrl'] = $HQ_music_url;
self::_replyData ( $msg, 'music' );
} /**
* 回复图文消息 格式如下:
array(
array($Title, $Description, $PicUrl , $Url),
array($Title, $Description, $PicUrl , $Url),
);
* @param array $articles
* @access public
* @return void
*/
static public function replyNews($articles)
{
foreach($articles as $k=>$v)
{
$arr[] = array('Title'=>$v[0],'Description'=>$v[1],'PicUrl'=>$v[2],'Url'=>$v[3]);
}
$msg ['ArticleCount'] = count ( $articles );
$msg ['Articles'] = $arr; self::_replyData ( $msg, 'news' );
} /**
* 将消息转发给客服
* @param string $kf_account 指定客服的账号,不传则由微信分配
* @access public
* @return void
*/
static public function replyKefu($kf_account='')
{
if(!empty($kf_account))
{
$msg ['TransInfo'][] = $kf_account;
}
self::_replyData($msg,'transfer_customer_service','KfAccount');
} /**
* 发送回复消息到微信平台
* @param array $msg 消息数组
* @param $msgType 消息类型
* @param string $item 包含子元素的元素名
* @access private
* @return void
*/
static private function _replyData($msg, $msgType, $item = 'item')
{
$msg ['ToUserName'] = strval(self::$fromUser);
$msg ['FromUserName'] = strval(self::$toUser);
$msg ['CreateTime'] = NOW_TIME;
$msg ['MsgType'] = $msgType;
if($_REQUEST ['doNotInit'])
{
dump($msg);
exit;
}
$xml = new \SimpleXMLElement ( '<xml></xml>' );
self::_data2xml ( $xml, $msg ,$item);
$str = $xml->asXML ();
self::addLog($str,2,'发送消息');//记录日志
echo $str;
} /**
* 组装xml数据
* @param $xml xml对象
* @param $data 要格式化的数组
* @param string $item 包含子元素的元素名
* @access public
* @return void
*/
static public function _data2xml($xml, $data, $item = 'item')
{
foreach ( $data as $key => $value )
{
is_numeric ( $key ) && ($key = $item);
if (is_array ( $value ) || is_object ( $value ))
{
$child = $xml->addChild ( $key );
self::_data2xml ( $child, $value, $item );
} else
{
if (is_numeric ( $value ))
{
$child = $xml->addChild ( $key, $value );
} else {
$child = $xml->addChild ( $key );
$node = dom_import_simplexml ( $child );
$node->appendChild ( $node->ownerDocument->createCDATASection ( $value ) );
}
}
}
}
/*************************************************** 发送消息响应微信 end ***************************************************/ /*************************************************** 上传下载文件 begin ***************************************************/
/**
* 上传临时素材
* @param $file 要发送的文件
* @param string $type 文件类型
* @access public
* @return mixed
*/
static public function uploadFile($file, $type = 'image')
{
// 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb)
$post_data = array('meida'=>"@".$file,'type'=>$type);
$url = "http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=".self::getAcctoken() ."&type=".$type;
return self::http_post($url,$post_data);
} /* 上传永久素材*/
static public function uploadYJFile($file, $type = 'image')
{
// 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb)
$post_data = array('meida'=>"@".$file,'type'=>$type);
$url = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=".self::getAcctoken();
return self::http_post($url,$post_data);
} /**
* 下载多媒体文件
* @param $media_id MediaId
* @access public
* @return void
*/
static public function downloadFile($media_id)
{
$url = '';
$filename = date('Y-m-d_H_i_s',time()).'.jpg';//设置保存的文件名
$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt ( $ch, CURLOPT_TIMEOUT, 60 );
$temp = curl_exec($ch);
if(@file_get_contents($filename,$temp) && !curl_errno($ch)) {
echo $filename;
}
else {
echo false;
} // TODO
}
/*************************************************** 上传下载文件 end ***************************************************/ /*************************************************** 执行http请求方法 begin ***************************************************/
/**
* 发送GET 请求
* @param string $url 地址
* @access public
* @return mixed
*/
static public function http_get($url)
{
$oCurl = curl_init ();
if (stripos ( $url, "https://" ) !== FALSE)
{
curl_setopt ( $oCurl, CURLOPT_SSL_VERIFYPEER, FALSE );
curl_setopt ( $oCurl, CURLOPT_SSL_VERIFYHOST, FALSE );
}
curl_setopt ( $oCurl, CURLOPT_URL, $url );
curl_setopt ( $oCurl, CURLOPT_RETURNTRANSFER, 1 );
$sContent = curl_exec ( $oCurl );
$aStatus = curl_getinfo ( $oCurl );
curl_close ( $oCurl );
return intval ( $aStatus ["http_code"] ) == 200 ? $sContent : false;
} /**
* 发送POST 请求
* @param string $url 地址
* @param array $param 参数
* @access public
* @return string content
*/
static public function http_post($url, $param)
{
$oCurl = curl_init ();
if (stripos ( $url, "https://" ) !== FALSE)
{
curl_setopt ( $oCurl, CURLOPT_SSL_VERIFYPEER, FALSE );
curl_setopt ( $oCurl, CURLOPT_SSL_VERIFYHOST, false );
}
curl_setopt ( $oCurl, CURLOPT_URL, $url );
curl_setopt ( $oCurl, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt ( $oCurl, CURLOPT_POST, true );
curl_setopt ( $oCurl, CURLOPT_POSTFIELDS, $param );
$sContent = curl_exec ( $oCurl );
$aStatus = curl_getinfo ( $oCurl );
curl_close ( $oCurl );
return intval ( $aStatus ["http_code"] ) == 200 ? $sContent : false;
}
/*************************************************** 执行http请求方法 end ***************************************************/ /*************************************************** 记录日志 begin ***************************************************/
/**
* @param $data 要记录的内容
* @param int $type 日志类型(1:Receive,2:Send,3:Sql,4:Signature)
* @param string $comment 备注信息
* @return null
*/
static public function addLog($data,$type=1,$comment='')
{
//日志存放文件夹名
$dirName = array('1' => 'Receive','2' => 'Send','3' => 'Sql','4'=>'Signature'); //构造日志文件名
$logDir = sprintf(self::LOG_DIR, $dirName[$type]); //格式化文件夹
$logName = sprintf(self::LOG_NAME,date('ymd')); //格式化文件名
if(!is_dir($logDir)) mkdir($logDir,0777,true); //如果文件夹不存在,创建
$logFile = $logDir.$logName; //日志最终文件名 //构造日志文件内容
$separator = str_repeat('*',42);
$content[] = "/$separator <- Begin:".date('Y-m-d H:i:s')." --> $separator/";
$content[] = trim(var_export($data,true),'\'');
if(!empty($comment)) $content[] = '备注: '.$comment;
$content[] = "/$separator <------------ End ------------> $separator/";
$logContent = PHP_EOL.implode(PHP_EOL,$content); //写入日志文件
$fp = fopen($logFile,"a+");
flock($fp, LOCK_EX) ;
fwrite($fp,$logContent);
flock($fp, LOCK_UN);
fclose($fp);
}
/*************************************************** 记录日志 end ***************************************************/ /*************************************************** oAuth网页授权获取用户信息 begin ***************************************************/ /**
* 网页授权获取用户信息
* @param $type 类型为openid或者userinfo
* @return mixed
*/
public static function oAuthGet($type)
{
if (!isset($_GET['code']))
{
//获取code码,以获取openid
$scopeArr = array('openid'=>'snsapi_base','userinfo'=>'snsapi_userinfo');
$scope = $scopeArr[$type];
$redirect_url = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].$_SERVER['QUERY_STRING']);
$url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".self::$member['appid']."&redirect_uri=$redirect_url&response_type=code&scope=$scope&state=oAuthInfo#wechat_redirect";
header ( 'Location: ' . $url );
}
else
{
/******************* 1.回调页面得到code *******************/
$code = $_GET['code'];
/******************* 2.用code去获取access_token和openid *******************/
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".self::$member['appid']."&secret=".self::$member['secret']."&code=$code&grant_type=authorization_code";
$result = self::http_get($url);
$result = json_decode($result,true);
$openid = $result['openid'];
if($result['scope'] == 'snsapi_base') //如果类型是snsapi_base,只返回openid
return $openid;
else
{
$access_token = $result['access_token']; //access_token
/******************* 3.用获取到的openid和access_token获取获取用户详细信息 *******************/
$url = "https://api.weixin.qq.com/sns/userinfo?access_token=$access_token&openid=$openid&lang=zh_CN";
$result = self::http_get($url);
return json_decode($result,true);
}
} }
/*************************************************** oAuth网页授权获取用户信息 end ***************************************************/ /*************************************************** 获取jssdk配置 begin ***************************************************/ /**
* 获取 JSSDK 配置
* @param bool $debug 是否开启调试模式
* @access public
* @return array
*/
public static function getJssdkConf($debug = false) {
$data = array(
'noncestr' => self::createNonceStr(),
'jsapi_ticket' => self::getJsApiTicket(),
'timestamp' => time(),
'url' => SERVER.__SELF__,
);
$str = 'jsapi_ticket='.$data['jsapi_ticket'].'&noncestr='.$data['noncestr'].'×tamp='.$data['timestamp'].'&url='.$data['url'];
return array(
'debug' => $debug,
'appId' => self::$member['appid'],
'timestamp' => $data['timestamp'],
'nonceStr' => $data['noncestr'],
'signature' => sha1($str),
);
} private static function getJsApiTicket() {
$mid = self::$member['id'];
$ticket = S('jsapi_ticket'.$mid);
if ($ticket == false) {
$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=".self::getAcctoken($mid);
$result =WeChat::http_get($url);
$result = json_decode($result, true);
$ticket = $result['ticket'];
S('jsapi_ticket'.$mid, $ticket, $result['expires_in'] - 1000);
}
return $ticket;
} private static function createNonceStr($length = 16) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
/*************************************************** 获取jssdk配置 end ***************************************************/ }
回复微信控制器:WeChatController
<?php
namespace Manage\Controller;
use Think\Controller;
use \Org\WeChat;
class WeChatController extends Controller
{
/* 接收微信的消息 */
public function index()
{
$id = intval(I('get.id'));
$info = M('Member')->where("status='1'")->find($id);
if (!is_array($info)) exit('请求无效!');
if (!empty ($_GET ['echostr']) && !empty ($_GET ["signature"]) && !empty ($_GET ["nonce"])) {
WeChat::checkSignature($info['token']); //微信接入验证
}
define('MID', $id); //定义公众号常量MID
WeChat::process(array($this, 'reply')); //处理消息
} /* 回复微信消息 */
public function reply($messageType, $data)
{
$controller = 'Process' . '\\Controller\\' . $messageType . 'Controller';
$class = new \ReflectionClass($controller);
$method = $class->getMethod('run');
$instance = $class->newInstance();
$method->invokeArgs($instance, array($data));
}
}
WeChat控制器,负责将请求分发给Process模块下对应控制器处理, 如Click类型由ClickController处理, Text类型由TextController处理,下面给出一个TextController控制器
<?php
namespace Process\Controller;
use \Org\WeChat; class TextController extends ProcessController
{
/* 用户点击菜单 */
public function run($data)
{
WeChat::replyText("您输入的内容是:" .$data['Content']);
}
} }
oAuth网页授权获取用户信息示例TestController
<?php
namespace Test\Controller;
use Think\Controller;
use \Org\WeChat;
class TestController extends Controller
{
/* 获取用户openid */
public function get_openid()
{
WeChat::setMember(2);
$openid = WeChat::oAuthGet('openid');
} /* 获取用户信息 */
public function get_userInfo()
{
WeChat::setMember(2);
$userinfo = WeChat::oAuthGet('userinfo');
var_dump($userinfo);
}
}
微信公众号开发模型WeChat的更多相关文章
- WeChat 微信公众号开发步骤
WeChat 微信公众号开发步骤 一.什么是微信公众号? 微信公众号是开发者或商家在微信公众平台上申请的应用账号,该帐号与QQ账号互通,通过公众号,商家可在微信平台上实现和特定群体的文字.图片.语音 ...
- .NET开发者如何愉快的进行微信公众号开发
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:这篇文章只是一个如何提高开发效率的简单指导和记录,不会涉及具体的微信公众号开发内容. ...
- 利用OpenShift托管Node.js Web服务进行微信公众号开发
最近写了一个微信的翻译机器人.用户只要关注该公众号,发送英文的消息,就能收到中文翻译的回复.有兴趣的读者可以扫描下面的二维码关注该公众号,尝试发送英文单词试试看.(有时候第一次发送单词会收到“该公众号 ...
- C#微信公众号开发系列教程四(接收普通消息)
微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...
- 微信公众号开发笔记(C#)
这篇文章还不错,使用 .net , 对微信用户的想公众号发送的文字进行回复.比较简单,自己可以修改更复杂的回复. 微信公众号开发笔记(C#) 原文地址 需求分析 根据用户在微信上发送至价值中国公众号 ...
- nodejs 中koa框架下的微信公众号开发初始篇
最近在搞微信公众号开发,后端采用的是nodejs下的koa框架,初识后端的菜鸟,自己搞难度太大了,网上找了很多文章,采用的中间件大都是express框架下的,不过好在爬了许多坑之后总算看见点曙光了,遂 ...
- 微信公众号开发C#系列-9、多公众号集中管理
1.概述 通过前面8篇关于微信开发相关文章的学习,我们已经对微信常用开发有了一个比较深入的了解.前面的文章都是基于某一特定公众号的,在现实业务中同一单位个体运营着不至一个公众号,此时就需要对多个公众号 ...
- 微信公众号开发C#系列-2、微信公众平台接入指南
概述 微信公众平台消息接口的工作原理大概可以这样理解:从用户端到公众号端一个流程是这样的,用户发送消息到微信服务器,微信服务器将接收到的消息post到用户接入时填写的url中,在url处理程序中,首先 ...
- [.NET] 使用 Senparc.Weixin 接入微信公众号开发:简单实现自动回复
使用 Senparc.Weixin 接入微信公众号开发:简单实现自动回复 目录 一.前提 二.基本配置信息简析 三.配置服务器地址(URL) 四.请求处理 一.前提 先申请微信公众号的授权,找到或配置 ...
随机推荐
- Ubuntu修改系统时间
在新版的ubuntu中,使用timedatectl 替换了ntpdate来进行时间管理. 1.查看当前时间状态 查看当前时间状态 timedatectl status : res@ubuntu:~$ ...
- Forward团队-爬虫豆瓣top250项目-开发文档
项目地址:https://github.com/xyhcq/top250 我在本次项目中负责写爬虫中对数据分析的一部分,根据马壮分析过的html,我来进一步写代码获取数据,具体的功能及实现方法我已经写 ...
- pycharm的console显示乱码和中文的配置
第一种方式: 在python脚本开始的地方加入指定编码方式 # -*- coding : UTF-8 -*- 第二种方式: 有些时候我们会得到这种格式的字符串: "name": & ...
- QT汇总
1.QT介绍及其在Linux下的安装 2.windows下安装QT并与visual studio 2017搭建开发环境 参考资料: QT官网资料 QT实战一二三 Qt资料大全 <Qt 实战一二三 ...
- ssh 使用 sed 替换的时候,替换的字符串有单双引号的时候怎么用
线上有一个脚本需要 ssh 登录远程机,然后完成特定文件中的某个值,替换的字符中有单引号,所以需要特定的写法,才能成功 1).ssh 远程执行命令,替换字符串中有单引号( ' ) ssh zhuzi@ ...
- PopupWindow计算弹出位置
1.首先自定义PopupWindow popWindowView= LinearLayout.inflate(context, R.layout.popupWindow,null); po ...
- 虚拟机Linux不能上网简单有效的解决办法
对于刚开始接触Linux系统的用户来说,先使用虚拟机Linux学习是不错的选择.但是在用虚拟机上网的时候,总是出现这样那样的错误,到底该怎么办呢?本文笔者和大家分享一下虚拟机Linux不能上网的简单有 ...
- How To Setup a CA
How To Setup a CA Original Version by Ian AldermanUpdated by Zach Miller Introduction You can set up ...
- [转] kaldi中FST的可视化-以yesno为例
http://blog.csdn.net/u013677156/article/details/77893661 1.kaldi解码过程 kaldi识别解码一段语音的过程是:首先提取特征,然后过声学模 ...
- 如何备份/迁移wordpress网站
暴力方法,完全备份网站目录及数据库,上传到新主机 首先,如果是迁移到其他新主机中,需要将新主机的环境配置好,还有对应网站目录和数据库,这些尽量和旧主机一样的设置 接下来,备份旧主机文件,找到网站目录, ...