2018年11月

为什么要在服务端装canvas? 因为并不是所有的客户端都能很好的支持canvas(比如微信小程序不能修改自定义字体),所以我们需要一个
能够在服务端生成图片的,然后将图片传输

安装node-canvas

1. 更新编译环境

sudo apt-get install libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev build-essential g++ -y

2. 安装node-canvas

npm install -g canvas

3. 测试代码

var Canvas = require('canvas'),
    canvas = new Canvas(300, 200),
    ctx = canvas.getContext('2d'),
    fs = require('fs');
 
var out = fs.createWriteStream(__dirname + '/image.png')
  , stream = canvas.createPNGStream();
 
stream.on('data', function(chunk){
  out.write(chunk);
});
 
//在左边画正方形
ctx.fillStyle = '#A00'    
ctx.fillRect(0, 30,50,50);   
  
 
//在右边画正方形
ctx.fillStyle = '#aaa'    
ctx.fillRect(50, 30, 50, 50);
 
//画文字
ctx.fillStyle = "#000";
ctx.font = "20px Arial";
ctx.fillText("Hello World", 0, 20);
 
//画一个圆
ctx.beginPath();
ctx.arc(30, 110, 20, 0, 2*Math.PI);
ctx.stroke();
ctx.fillStyle = "green";                                                                                                                          
ctx.fill();
ctx.save();  

可能遇到的问题

如果你按上述方法操作,并且运行成功了。那便是极好的

1. 自定义字体

// You need to call it before the Canvas is created
Canvas.registerFont('comicsans.ttf', {family: 'Comic Sans'});

var canvas = new Canvas(500, 500),
  ctx = canvas.getContext('2d');

ctx.font = '12px "Comic Sans"';
ctx.fillText(250, 10, 'Everyone hates this font :(');
不过可能会发现Canvas.registerFont is not a function这是因为npm版本的没有这个函数。

所以你需要去找另一个github版https://github.com/chearon/node-canvas#12971f64a66b

git clone 下来

然后将Canvas = require('canvas')改成require('./node-canvas'),
var canvas = new Canvas(300, 200)改成var canvas = new Canvas.Canvas(300, 200)

2. Error: Cannot find module '../build/Release/canvas.node'

如果遇到这个问题,请cd进你的node-canvas目录执行npm install

如果还是不行,请执行npm install -g node-gyp

然后再cd项目目录执行node-gyp rebuild,then cd 进node-canvas同样执行node-gyp rebuild

如果成功则会出现

编译过程

示例代码

我的项目目录

.
├── 1.html
├── composer.json
├── font
├── fz.ttf
├── img
├── index.js
├── node-canvas
├── node_modules
├── package.json
└── package-lock.json

我的代码

var fs = require('fs'),path = require('path');
var http = require('http'),url = require("url");
var Canvas = require('./node-canvas'),Image = Canvas.Image;
var Fonts = [];
var filePath = path.resolve('./font');

let promise = new Promise(function(resolve, reject) {
  let i=0;
  fs.readdir(filePath,function(err,files){  
    if(err){  
      console.warn(err)  
    }else{
      files.forEach(function(filename){
        Canvas.registerFont(filePath + "/" + filename, {family: "font" + i});
        console.log(i);
        i++;
      });
    }
  });
  
});

promise.then(function() {
  console.log("ASDF");
  Fonts.forEach((Element) =>{
    console.log(Element);
  });
});

console.log('Hi!');


http.createServer(function (req, res) {
  var params = url.parse(req.url, true).query;
  var str = params.str + '\r',site = params.site;
  var row =  1,col = 15,width = 1500;
  row = str.length / 15 + 1;
  var fontsize = width/col;
  var height = fontsize * row + 200;
  if(height < 1000){height = 1000}
  var canvas = new Canvas.Canvas(width, height), ctx = canvas.getContext('2d')
  res.writeHead(200,{"Content-Type": "image/png"});
  ctx.fillStyle = '#FFF';
  ctx.fillRect(0,0,canvas.width, canvas.height);
  ctx.fillStyle = '#000';
  if(row < 2){
    let num = str.length
    fontsize = 1200 / num;
    ctx.font = fontsize + 'px "font'+ site +'"';
    ctx.fillText(str,( width - num * fontsize ) / 2, (height-fontsize)/2 -200 + fontsize);
  }
  else{
    ctx.font = fontsize + 'px "font'+ site +'"';
    for(let i = 0;i < row ; i++){
      ctx.fillText(str.substring(i*15,(i+1)*15), 0, fontsize*(i+1));
    }
  }
  
  fs.readFile(__dirname + '/img/brand.png', function(err, squid){
    if (err) throw err;
    img = new Image;
    img.src = squid;
    ctx.fillStyle = '#42b983';
    ctx.fillRect(0,canvas.height - 230,canvas.width, 230);
    ctx.drawImage(img, canvas.width - img.width / 2 - 50, canvas.height - img.height / 2 - 50, img.width / 2, img.height / 2);
    res.end(canvas.toBuffer());
  });
}).listen(8080);

效果展示

天地玄黄

  1. URL跳转,
    链接跳转
    https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$this->appid."&redirect_uri=".urlencode("http://192.168.43.46/auit/index.php?c=app&m=oauth")."&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
  2. 用户进入页面,拿code换取ACCESS_TOKEN, 请求代码

    file_get_contents("https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->appid."&secret=".$this->secret."&code=".$_GET['code']."&grant_type=authorization_code");
  3. 用ACCESS_TOKEN换取用户数据,请求代码

    file_get_contents("https://api.weixin.qq.com/sns/userinfo?access_token=".$data->access_token."&openid=".$data->openid."&lang=zh_CN")
流程示例代码
public function oauth(){
      if (isset($_GET['code'])){
          $data=json_decode(file_get_contents("https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->appid."&secret=".$this->secret."&code=".$_GET['code']."&grant_type=authorization_code"));
          $userInfo=json_decode(file_get_contents("https://api.w
         eixin.qq.com/sns/userinfo?access_token=".$data->access_token."&openid=".$data->openid."&lang=zh_CN"));
          $user = array(
              'openid'  => $userInfo->openid,
              'nickname'     => $userInfo->nickname,
              'headimgurl' => $userInfo->headimgurl
          );
          $this->session->set_userdata($user);
          $this->db->replace('user', $user);
          redirect('client');
      }else{
          echo "出现未知错误,如果重复出现该错误,请联系开发者。错误代码:Oauth:10203";
      }
  }

php密码操作(PHP 5 >= 5.5.0, PHP 7)

  1. 加密操作:string password_hash ( string $password , int $algo [, array $options ] )
示例:
password_hash("admin", PASSWORD_DEFAULT); 
  1. 判断操作: bool password_verify ( string $password , string $hash )
示例:
password_verify($password, $admin_data->row()->password)

本文实践平台:腾讯云(qcloud.com)

首先我们来看看腾讯云官方的解决方案示意图
0.png

看懂了吗?看没看懂都没关系我们开始走一遍就好了。大致步骤如下:

  1. 购买腾讯云微信小程序解决方案
  2. 部署 mysql 实例到云数据库
  3. 部署网站到服务器,使网站外网可访问
  4. 将网站与数据库连接起来
  5. 配置 SSL 证书,使网站可 https 访问
  6. 构建负载均衡,使用户可以通过负载均衡的方式访问
  7. 制作服务器镜像,将可成功访问的服务器复制
  8. 新建 N(N>0)台服务器,将服务器重装为自定义镜像
  9. test

详细如下:

  • 购买腾讯云微信小程序解决方案
  1. 进入腾讯云官网(https://www.qcloud.com)

  1. 选择解决方案>微信小程序解决方案

就选择 3 元新购活动吧,我已经购买过了,就不再这儿演示怎么购买了。

  1. 购买成功之后腾讯云会下发资源。

succeed:此过程成功标志为资源下发成功,以及收到如下站内信。
  • 部署 mysql 实例到云数据库

  1. 根据上图所提供的地址,使用数据库连接工具(如 Navicat)连接数据库进行数据传输。_

  1. 数据传输_

succeed:此过程的成功标志为,在远程数据库中可查看到相应的表和数据
  • 部署网站到服务器,使网站外网可访问
  1. 首先我们对腾讯云下发的 demo 服务器进行重装系统(精神洁癖,不重装不舒服)_
注:不重装的话,网站的根目录在/data/release/php_weapp_demo > \_ > * > > >
我这儿装的是 centOS 6.5。版本不同可能会对应的软件安装方式不同。 2.*为服务器安装 apache\_ #安装 apache
root@localhost ~]# yum -y install httpd

开机自启动

[root@localhost ~]# chkconfig httpd on

启动 httpd 服务

[root@localhost ~]# service httpd start

安装 apache 一些扩展

root@localhost ~]# yum -y install httpd-manual mod_ssl mod_perl mod_auth_mysql

succeed:此步骤成功标志为访问http://localhost  或 http://本机IP  ,应该会看到 Apache 的测试页面

这里需要注意 iptables 的设置哦。

安装 php[root@localhost ~]# yum -y install php php-mysql

安装 php 常用扩展

[root@localhost ~]# yum search php
[root@localhost ~]# yum -y install gd php-gd gd-devel php-xml php-common php-mbstring php-ldap php-pear php-xmlrpc php-imap
 ### 重启 httpd 服务,这一步很重要
[root@localhost ~]# service httpd restart
然后,我们提供 php 页面,测试
[root@localhost ~]# cd /var/www/html/
[root@localhost html]# vi index.php
<?php
    phpinfo();
<php>
succeed:此步骤成功标志为,出现传说中的 phpinfo()界面

后记:不知不觉,已经写了有这么多了!本来想一篇写完的,看了一下可能篇幅实在是太长了。先这样吧。敬请期待下一篇吧!

到了这步的时候,你只需要把网站源代码(例如博客,或者自己开发的网站)上传到目录/var/www/html/就好了。windows 操作系统可以利用工具(如 winscp)上传。觉得有用的就点赞收藏一下吧。谢谢大家的支持。

本文环境

操作系统: Ubuntu 16.04.3
Python版本: 3.5.2
Django版本: 2.0.4
nginx版本: 1.10.3

本文平台为腾讯云1核1G系统
我的项目文件名为: dgutpsy

安装pip3(python3 的pip)

sudo apt-get install python3-pip

2018-04-10-20-07-25.png

安装成功后运行pip3将会出现

2018-04-10-20-09-19.png

安装uwsgi

pip install uwsgi

2018-04-10-20-17-19.png

测试uwsgi运行状态

新建文件test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"]
有些教程说是 return "hello world"
但是这样其实会出现访问空白的情况, 我的是Python3的环境,需要对hello world进行编码.
而如果你是Python2的环境,你应该写return "hello world"

使用uwsgi运行该文件

uwsgi --http :8000 --wsgi-file test.py
此语句的意思是,使用uwsgi运行test.py文件, 采用http模式, 端口8000

2018-04-10-20-44-49.png

访问页面

好啦,可以看到亲切的hello world 就说明uwsgi运行成功了

2018-04-10-20-39-21.png

TIPS: 如果你访问不了,请先检查腾讯云安全组端口是否开放8000端口

安装Django

pip3 install Django
如在python3里面import django没有报错则安装成功.

2018-04-10-20-55-49.png

上传项目代码

现在我们开始上传项目代码

2018-04-10-20-42-25.png

使用MobaXterm的sftp工具拖进来,[笑着哭]不要问我为什么不用ftp,这个方便.

确认代码运行正常

切进项目目录,运行
python3 manage.py runserver 0.0.0.0:8000

2018-04-10-20-59-03.png

访问页面

2018-04-10-21-01-32.png

不太对?这是因为设置了ALLOWED_HOSTS的原因
我们在setting.py里设置一下
ALLOWED_HOSTS = ['*']

再次访问页面

2018-04-10-21-05-34.png

OK!

uswgi运行项目

 uwsgi --http :8000 --chdir /home/ubuntu/dgutpsy  --wsgi dgutpsy.wsgi
这个语句的意思与上相似,只不过是多了一个工作路径和wsgi文件
2018-04-10-21-05-34.png
开什么玩笑? 你觉得没变化?

至此

我们可以暂定以下内容
  1. 项目没问题.
  2. 项目配置没问题
  3. uwsgi没问题
  4. 对项目的支持环境没问题

接下来, 我们开始配置nginx

安装nginx

sudo apt-get install nginx

测试nginx运行状态

2018-04-10-21-18-53.png

nginx 安装成功

修改nginx配置

文件路径"/etc/nginx/sites-enabled/default"

别再费力找nginx.conf啦,新版本已经没有这个文件的.

我的
upstream django {
        server 127.0.0.1:8001; #web的socket端口
    }
server {
    listen 80 default_server;
    listen [::]:80 default_server;
 
    index index.html index.htm index.nginx-debian.html;

    server_name _;

    location / {
        root /home/ubuntu/dgutpsy; #项目目录
        uwsgi_pass django;
        include /home/ubuntu/dgutpsy/uwsgi_params; #uwsgi_params文件的地址
    }
}

完整的uwsgi_params文件内容应该是

uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;
没有这个文件,或者这个文件写错是会报错的哦.

访问测试502

2018-04-10-21-37-49.png

这是因为我们的socket通信还没开始呢!

nginx 与 uwsgi通信

先使用hello world测试
uwsgi --socket :8001 --wsgi-file test.py

访问测试页面

图片描述


至此: nginx 与 uwsgi通信成功!

TIPS: 这里你是无法通过在浏览器里面访问8001端口来判断是否启动的,因为它是socket协议

让uwsgi后台运行

这样虽然看似可以, 但是当你关闭ssh时,又会出现502了!

这是因为当你关闭这个ssh进程时,uwsgi进程也被终止了.
而且,每次启动都要输一串好长的命令,好不麻烦!

这个时候,我们需要用到一个东西, 那就是ini配置文件启动.
其中daemonize = /home/ubuntu/dgutpsy/test.log的意思就是后台运行并规定日志输出目录。

新建test.ini

[uwsgi]
socket = 127.0.0.1:8001
wsgi-file = /home/ubuntu/dgutpsy/test.py
daemonize = /home/ubuntu/dgutpsy/test.log 
uwsgi --ini test.ini

niginx与Django项目通信

新建dgutpsy.ini

[uwsgi]
socket = 127.0.0.1:8001
chdir           = /home/ubuntu/dgutpsy
module          = dgutpsy.wsgi
master          = true
processes       = 1 

threads = 2 
max-requests = 6000

daemonize = /home/ubuntu/dgutpsy/run.log

然后运行

uwsgi --ini dgutpsy.ini

域名映射

添加域名>解析consult.psyannabel.cn

访问页面

后记:

Q&A:
Q: 能用manage.py运行的,为什么要用uwsgi?

A: 单进程的manage.py, 能和web服务器uwsgi比ma

Q: 能用uwsgi的,为什么还要用nginx?

A: uwsgi虽然是web服务器, 但是它在处理静态文件时, 并没有nginx来得优秀.

Q: 大致流程?

A: nginx运行web处理http请求, nginx使用socket与uwsgi通信,将动态部分转让交给uwsgi处理

Q: 为啥我的test.py运行不了?

A: 如果端口开放没有问题,那么请检查Python版本对应的return

前言

醉月老哥的微信助手:
不要问我为什么起这个名字,我也不知道!
这两天天气冷,在脑海里构想这个,之后便开始着手做了。
开始日期:2017年12月15日 13时47分25秒

醉月老哥的微信助手

功能定位

立志做一个对接全网内容的助手,其内容包括但不限于:糗事百科,今日头条,简书,MSDN,php.net,百度翻译,搜索引擎。争取做到微信在手,天下我有!有好的想法或者建议欢迎联系我!

特别感谢: @Goff, @Annabel

现有功能介绍

1. 糗事百科

使用说明

公众号回复"糗事百科"

效果展示

糗事百科:效果展示

:TODO

虽然看似基本功能完成了,但是会有一个小问题:
当爬取的内容为,图片分享时,并不能展示其对应的图片

2. 今日头条

今日头条-使用说明

公众号回复“今日头条"

今日头条-效果展示

今日头条:效果展示

今日头条-:TODO

我怎么感觉这个娱乐新闻偏多呢?(是头条热点的问题?)
1.将内容集中与政治,社会,科技

3. 醉月老哥的微信助手

醉月老哥的微信助手-使用说明

公众号回复"醉月老哥的微信助手"

醉月老哥的微信助手-效果展示

醉月老哥的微信助手:效果展示

4.搜索新闻

搜索新闻-使用说明

回复'news(关键词)'搜索新闻,例如news(江歌),搜索关于江歌的新闻

搜索新闻-效果展示

enter description here

搜索新闻-:TODO

让新闻来源可指向

公众号二维码

enter description here

源代码地址

醉月老哥的微信助手

更新说明

更新说明