pip 安装MySQL-python:EnvironmentError: mysql_config not found

atool 发表了文章 • 0 个评论 • 777 次浏览 • 2016-11-21 20:43 • 来自相关话题

网上很多做法是:
 首先 find / -name mysql_config 在/usr/bin/下发现了这个文件
然后修改MySQL-python-1.2.5目录下的site.cfg文件
去掉mysql_config=XXX这行的注释,并改成mysql_config=/usr/bin/mysql_config(以mysql_config文件所在机器上的目录为准)


然后 python setup.py install
 
但是这样安装会出现:ExtractionError: Can't extract file(s) to egg cache

The following error occurred while trying to extract file(s) to the Python egg
cache:

[Errno 13] Permission denied: '/root/.cache'

The Python egg cache directory is currently set to:

/root/.cache/Python-Eggs

Perhaps your account does not have write access to this directory? You can
change the cache directory by setting the PYTHON_EGG_CACHE environment
variable to point to an accessible directory.
最后解决办法:
 
首先:apt-get install libmysqlclient-dev
 
然后再 pip install MySQL-python,解决。 查看全部
网上很多做法是:
 
首先 find / -name mysql_config 在/usr/bin/下发现了这个文件
然后修改MySQL-python-1.2.5目录下的site.cfg文件
去掉mysql_config=XXX这行的注释,并改成mysql_config=/usr/bin/mysql_config(以mysql_config文件所在机器上的目录为准)


然后 python setup.py install
 
但是这样安装会出现:
ExtractionError: Can't extract file(s) to egg cache

The following error occurred while trying to extract file(s) to the Python egg
cache:

[Errno 13] Permission denied: '/root/.cache'

The Python egg cache directory is currently set to:

/root/.cache/Python-Eggs

Perhaps your account does not have write access to this directory? You can
change the cache directory by setting the PYTHON_EGG_CACHE environment
variable to point to an accessible directory.

最后解决办法:
 
首先:apt-get install libmysqlclient-dev
 
然后再 pip install MySQL-python,解决。

paramiko使用private key SSH登陆服务器

atool 发表了文章 • 0 个评论 • 1462 次浏览 • 2016-08-01 15:24 • 来自相关话题

本文介绍的是使用 SSH方式通过密钥登录 服务器的方法。主要在windows上使用paramiko登陆linux服务器,分成为四步:
 
一、服务器生成rsa key
aaa@onlinegame-14-121:~/.ssh$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/aaa/.ssh/id_rsa): id_rsa_forpy
id_rsa_forpy already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in id_rsa_forpy.
Your public key has been saved in id_rsa_forpy.pub.
The key fingerprint is:
27:04:9f:0b:21:73:a7:2a:cd:4e:9e:43:2a:45:c2:29 aaa@onlinegame-14-121
The key's randomart image is:
+--[ RSA 2048]----+
| o + . |
|. . + * . |
|Eo. o + |
|.o o . o . |
| o * S . |
| . B . o |
|. . |
| . . |
| |
+-----------------+其中passphrase我没有输入,这样用python登陆的时候,就可以无密码登陆了。
注意,是在你将要登陆的linux服务器上生成key。
 
二、公钥添加到authorized_keys中
[aaa@host ~]$ cd .ssh
[aaa@host .ssh]$ cat id_rsa_forpy.pub >> authorized_keys如此便完成了公钥的安装。有些时候,可能会有一些权限问题,可以执行如下:
[aaa@host .ssh]$ chmod 600 authorized_keys
[aaa@host .ssh]$ chmod 700 ~/.ssh

 三、服务器开启密钥登陆功能
 
一般情况下,服务器可能是开启,如果没有,可以做下面的操作。
编辑 /etc/ssh/sshd_config 文件,进行如下设置:
RSAAuthentication yes
PubkeyAuthentication yes修改配置文件之后,需要重启ssh
service sshd restart
四、使用paramiko登陆执行命令
 
将上述第一步生成的id_rsa_forpy(密钥)下载到windows机器上,然后用他进行代码登陆。
 
使用pip安装paramiko,然后执行代码即可。
pip install paramikoPython代码如下:
 
# -*- coding: utf-8 -*-

import paramiko
import StringIO

ip = 'xx.xx.xxx.xxx'
username = 'aaa'
port = 22

key_string = '''-----BEGIN RSA PRIVATE KEY-----
xxxxxxx
-----END RSA PRIVATE KEY-----
'''
not_really_a_file = StringIO.StringIO(key_string)
private_key = paramiko.RSAKey.from_private_key(not_really_a_file)

paramiko.util.log_to_file('ssh.log')

s = paramiko.SSHClient()

s.load_system_host_keys()
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())

print "Starting"
s.connect(ip, port, username, pkey=private_key)

stdin,stdout,stderr=s.exec_command('ls -lh')
print stdout.read()
s.close()

not_really_a_file.close()执行之后,就可以看到打印出aaa账户home目录的文件列表了。 查看全部
本文介绍的是使用 SSH方式通过密钥登录 服务器的方法。主要在windows上使用paramiko登陆linux服务器,分成为四步:
 
一、服务器生成rsa key
aaa@onlinegame-14-121:~/.ssh$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/aaa/.ssh/id_rsa): id_rsa_forpy
id_rsa_forpy already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in id_rsa_forpy.
Your public key has been saved in id_rsa_forpy.pub.
The key fingerprint is:
27:04:9f:0b:21:73:a7:2a:cd:4e:9e:43:2a:45:c2:29 aaa@onlinegame-14-121
The key's randomart image is:
+--[ RSA 2048]----+
| o + . |
|. . + * . |
|Eo. o + |
|.o o . o . |
| o * S . |
| . B . o |
|. . |
| . . |
| |
+-----------------+
其中passphrase我没有输入,这样用python登陆的时候,就可以无密码登陆了。
注意,是在你将要登陆的linux服务器上生成key。
 
二、公钥添加到authorized_keys中
[aaa@host ~]$ cd .ssh
[aaa@host .ssh]$ cat id_rsa_forpy.pub >> authorized_keys
如此便完成了公钥的安装。有些时候,可能会有一些权限问题,可以执行如下:
[aaa@host .ssh]$ chmod 600 authorized_keys
[aaa@host .ssh]$ chmod 700 ~/.ssh

 三、服务器开启密钥登陆功能
 
一般情况下,服务器可能是开启,如果没有,可以做下面的操作。
编辑 /etc/ssh/sshd_config 文件,进行如下设置:
RSAAuthentication yes
PubkeyAuthentication yes
修改配置文件之后,需要重启ssh
service sshd restart

四、使用paramiko登陆执行命令
 
将上述第一步生成的id_rsa_forpy(密钥)下载到windows机器上,然后用他进行代码登陆。
 
使用pip安装paramiko,然后执行代码即可。
pip install paramiko
Python代码如下:
 
# -*- coding: utf-8 -*-

import paramiko
import StringIO

ip = 'xx.xx.xxx.xxx'
username = 'aaa'
port = 22

key_string = '''-----BEGIN RSA PRIVATE KEY-----
xxxxxxx
-----END RSA PRIVATE KEY-----
'''
not_really_a_file = StringIO.StringIO(key_string)
private_key = paramiko.RSAKey.from_private_key(not_really_a_file)

paramiko.util.log_to_file('ssh.log')

s = paramiko.SSHClient()

s.load_system_host_keys()
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())

print "Starting"
s.connect(ip, port, username, pkey=private_key)

stdin,stdout,stderr=s.exec_command('ls -lh')
print stdout.read()
s.close()

not_really_a_file.close()
执行之后,就可以看到打印出aaa账户home目录的文件列表了。

【BUG】Flask werkzeug secure_filename中文问题

atool 发表了文章 • 0 个评论 • 1312 次浏览 • 2016-04-27 16:51 • 来自相关话题

使用Flask做web开发的时候,经常用到上传文件,然后Flask官方推荐使用secure_filename方法对上传的文件名进行处理。
结果这个方法对于中文文件处理并不好,导致非常隐晦的BUG。
如下为测试代码:#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Created on 2016年3月31日

@author: hustcc
'''
from werkzeug.utils import secure_filename

print secure_filename("My cool movie.mov")
print secure_filename("../../../etc/passwd")
print secure_filename(u'i contain cool \xfcml\xe4uts.txt')

print secure_filename(u'中文文件名.txt')
print secure_filename(u'中文文件名+English13.txt')打印结果如下:




注意第4,5点输出结果。中文直接被删除,导致文件名直接变成后缀,连“.”都没有了。官方的Flask demo也是害人。
建议直接用md5代替这个方法来取得安全性。 查看全部
使用Flask做web开发的时候,经常用到上传文件,然后Flask官方推荐使用secure_filename方法对上传的文件名进行处理。
结果这个方法对于中文文件处理并不好,导致非常隐晦的BUG。
如下为测试代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Created on 2016年3月31日

@author: hustcc
'''
from werkzeug.utils import secure_filename

print secure_filename("My cool movie.mov")
print secure_filename("../../../etc/passwd")
print secure_filename(u'i contain cool \xfcml\xe4uts.txt')

print secure_filename(u'中文文件名.txt')
print secure_filename(u'中文文件名+English13.txt')
打印结果如下:
未命名.png

注意第4,5点输出结果。中文直接被删除,导致文件名直接变成后缀,连“.”都没有了。官方的Flask demo也是害人。
建议直接用md5代替这个方法来取得安全性。

.htaccess 配置 Gzip 压缩

atool 发表了文章 • 0 个评论 • 587 次浏览 • 2016-04-25 09:47 • 来自相关话题

Gzip有利于减少服务器流量压力,压缩比可以达到70%。



# BEGIN GZIP
<ifmodule mod_deflate.c>
AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript
</ifmodule>
# END GZIP<IfModule mod_filter.c>
AddOutputFilterByType DEFLATE "application/atom+xml" \
"application/javascript" \
"application/json" \
"application/ld+json" \
"application/manifest+json" \
"application/rdf+xml" \
"application/rss+xml" \
"application/schema+json" \
"application/vnd.geo+json" \
"application/vnd.ms-fontobject" \
"application/x-font-ttf" \
"application/x-javascript" \
"application/x-web-app-manifest+json" \
"application/xhtml+xml" \
"application/xml" \
"font/eot" \
"font/opentype" \
"image/bmp" \
"image/svg+xml" \
"image/vnd.microsoft.icon" \
"image/x-icon" \
"text/cache-manifest" \
"text/css" \
"text/html" \
"text/javascript" \
"text/plain" \
"text/vcard" \
"text/vnd.rim.location.xloc" \
"text/vtt" \
"text/x-component" \
"text/x-cross-domain-policy" \
"text/xml"

</IfModule> 查看全部
Gzip有利于减少服务器流量压力,压缩比可以达到70%。
未命名.png
# BEGIN GZIP
<ifmodule mod_deflate.c>
AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript
</ifmodule>
# END GZIP
<IfModule mod_filter.c>
AddOutputFilterByType DEFLATE "application/atom+xml" \
"application/javascript" \
"application/json" \
"application/ld+json" \
"application/manifest+json" \
"application/rdf+xml" \
"application/rss+xml" \
"application/schema+json" \
"application/vnd.geo+json" \
"application/vnd.ms-fontobject" \
"application/x-font-ttf" \
"application/x-javascript" \
"application/x-web-app-manifest+json" \
"application/xhtml+xml" \
"application/xml" \
"font/eot" \
"font/opentype" \
"image/bmp" \
"image/svg+xml" \
"image/vnd.microsoft.icon" \
"image/x-icon" \
"text/cache-manifest" \
"text/css" \
"text/html" \
"text/javascript" \
"text/plain" \
"text/vcard" \
"text/vnd.rim.location.xloc" \
"text/vtt" \
"text/x-component" \
"text/x-cross-domain-policy" \
"text/xml"

</IfModule>

uwsgi部署到nginx出现invalid request block size: 4161 (max 4096)...skip问题

atool 发表了文章 • 0 个评论 • 1334 次浏览 • 2016-04-22 14:11 • 来自相关话题

使用Flask制作一个网页平台之后,登陆使用openid登陆,然后使用uwsgi服务部署到nginx上,运行起来没有什么问题,但是偶尔在登陆的时候出现502的错误,一般登陆成功之后后面的任何操作都不会出错。

查看uwsgi的log之后,发现出现这样的一个错误:

invalid request block size: 4161 (max 4096)...skip

之前一个没有去详细搜索过,也没有具体去看错误产生的原因,因为只是偶尔出现,并且有时候重试的时候是可以登陆的,所以没有太多的去关注,今天因为在会议演示的过程中又出现这个问题,所以不得不重视了。

搜索一下,其实问题很简单:url地址长度超过了4096个字符,而4096就是uwsgi配置中buffer-size的默认值,所以只需要将buffer-size改大一点即可。

我是使用uwsgi -x 指定uwsgi配置文件来启动服务器的,所以只需要修改成以下方式启动即可:

uwsgi -x platform.uwsgi.xml --buffer-size 32768

即在后面增加一个 --buffer-size 32768

问题基本就解决了,至于为什么这个问题是偶尔出现?那是因为openid登陆的时候会携带一个参数叫next_url,这个地址是用来指定登陆成功之后返回到哪里地址,如果这个next_url太长就会导致url地址超过4096,有时候next_url=/,即网站根地址,url地址长度就不会超过4096。另外还和openid返回的登陆人信息长度有关系,导致有些人从来不会出现这个错误,有些人偶尔出现这个问题。

Enjoy~ 查看全部
使用Flask制作一个网页平台之后,登陆使用openid登陆,然后使用uwsgi服务部署到nginx上,运行起来没有什么问题,但是偶尔在登陆的时候出现502的错误,一般登陆成功之后后面的任何操作都不会出错。

查看uwsgi的log之后,发现出现这样的一个错误:

invalid request block size: 4161 (max 4096)...skip

之前一个没有去详细搜索过,也没有具体去看错误产生的原因,因为只是偶尔出现,并且有时候重试的时候是可以登陆的,所以没有太多的去关注,今天因为在会议演示的过程中又出现这个问题,所以不得不重视了。

搜索一下,其实问题很简单:url地址长度超过了4096个字符,而4096就是uwsgi配置中buffer-size的默认值,所以只需要将buffer-size改大一点即可。

我是使用uwsgi -x 指定uwsgi配置文件来启动服务器的,所以只需要修改成以下方式启动即可:

uwsgi -x platform.uwsgi.xml --buffer-size 32768

即在后面增加一个 --buffer-size 32768

问题基本就解决了,至于为什么这个问题是偶尔出现?那是因为openid登陆的时候会携带一个参数叫next_url,这个地址是用来指定登陆成功之后返回到哪里地址,如果这个next_url太长就会导致url地址超过4096,有时候next_url=/,即网站根地址,url地址长度就不会超过4096。另外还和openid返回的登陆人信息长度有关系,导致有些人从来不会出现这个错误,有些人偶尔出现这个问题。

Enjoy~

一个轻量级 Python 装饰器的缓存库——wrapcache

atool 发表了文章 • 0 个评论 • 708 次浏览 • 2016-04-22 13:22 • 来自相关话题

A python Function / Method OUTPUT cache system base on function Decorators.
github 地址:https://github.com/hustcc/wrapcache




 
一、使用场景

经常会在某些很小的场合需要缓存一些数据,提高一些性能,而这种缓存又不是经常需要,比如:

两个进程共享数据库,其中只读进程读取数据做一些操作,这个时候,可以将数据库内容缓存一下,避免重复读数据库;

一个web页面数据太多,然而页面并不需要完全的实时性,这个时候就可以将页面内容完全缓存,在过期时间之后,不读数据库,不进行大量计算,这种在一些报告页面非常常见。

这两个场景其实挺常见的,要完成也不难,无非就是存到python 字段,加一个时间戳,判断过期,如果是redis,就直接存redis,并赋予timeout时间就ok了。

自己因为经常遇到这种场景,所以将其封装成一个python库,方便使用。

二、如何使用

使用简单,只需要要在方法上面加一个装饰器即可缓存,并且设置缓存过期时间。import wrapcache
@wrapcache.wrapcache(timeout = 60)
def need_cache_function(input, t = 2, o = 3): sleep(2)
return random.randint(1, 100)以上即可,第一次运行需要 2 秒,第二次运行(过期时间 60 秒之内)瞬间给出缓存结果。适合于小场景的方法缓存。
 
三、安装方法
 
首先 pip install wrapcache,支持python2和python3。

然后import wrapcache。

最后在需要缓存的方法上加上装饰器即可@wrapcache.wrapcache(timeout = 3)

其中 @wrapcache.wrapcache(timeout = 3, adapter = RedisAdapter) 有两个参数:

timeout, 过期时间,默认为-1,不缓存数据

adapter,存储器,默认为MemoryAdapter(存到python的全局字典中),可选RedisAdapter(存储到redis中)

注意:如果选择adapter = RedisAdapter,则需要在使用前设置redis市里 调用 RedisAdapter.db = redis_instanceREDIS_CACHE_POOL = redis.ConnectionPool(host = 'xx.xxx.xx.xxx', port = 6379, password = 'redis_pwd', db = 2)
REDIS_CACHE_INST = redis.Redis(connection_pool = REDIS_CACHE_POOL, charset = 'utf8')
RedisAdapter.db = REDIS_CACHE_INST #初始化装饰器缓存四、TODO

目前是使用内存 dict 和 redis 存储缓存,后续要支持将 memcached 等服务器中,只需要补充 adapter 中代码,实现对应方法即可。

欢迎 push requst 和 issue 。 查看全部
A python Function / Method OUTPUT cache system base on function Decorators.
github 地址:https://github.com/hustcc/wrapcache
未命名.png

 
一、使用场景

经常会在某些很小的场合需要缓存一些数据,提高一些性能,而这种缓存又不是经常需要,比如:

两个进程共享数据库,其中只读进程读取数据做一些操作,这个时候,可以将数据库内容缓存一下,避免重复读数据库;

一个web页面数据太多,然而页面并不需要完全的实时性,这个时候就可以将页面内容完全缓存,在过期时间之后,不读数据库,不进行大量计算,这种在一些报告页面非常常见。

这两个场景其实挺常见的,要完成也不难,无非就是存到python 字段,加一个时间戳,判断过期,如果是redis,就直接存redis,并赋予timeout时间就ok了。

自己因为经常遇到这种场景,所以将其封装成一个python库,方便使用。

二、如何使用

使用简单,只需要要在方法上面加一个装饰器即可缓存,并且设置缓存过期时间。
import wrapcache
@wrapcache.wrapcache(timeout = 60)
def need_cache_function(input, t = 2, o = 3): sleep(2)
return random.randint(1, 100)
以上即可,第一次运行需要 2 秒,第二次运行(过期时间 60 秒之内)瞬间给出缓存结果。适合于小场景的方法缓存。
 
三、安装方法
 
首先 pip install wrapcache,支持python2和python3。

然后import wrapcache。

最后在需要缓存的方法上加上装饰器即可@wrapcache.wrapcache(timeout = 3)

其中 @wrapcache.wrapcache(timeout = 3, adapter = RedisAdapter) 有两个参数:

timeout, 过期时间,默认为-1,不缓存数据

adapter,存储器,默认为MemoryAdapter(存到python的全局字典中),可选RedisAdapter(存储到redis中)

注意:如果选择adapter = RedisAdapter,则需要在使用前设置redis市里 调用 RedisAdapter.db = redis_instance
REDIS_CACHE_POOL = redis.ConnectionPool(host = 'xx.xxx.xx.xxx', port = 6379, password = 'redis_pwd', db = 2)
REDIS_CACHE_INST = redis.Redis(connection_pool = REDIS_CACHE_POOL, charset = 'utf8')
RedisAdapter.db = REDIS_CACHE_INST #初始化装饰器缓存
四、TODO

目前是使用内存 dict 和 redis 存储缓存,后续要支持将 memcached 等服务器中,只需要补充 adapter 中代码,实现对应方法即可。

欢迎 push requst 和 issue 。

Flask + gunicorn + nginx 部署Web

atool 发表了文章 • 0 个评论 • 484 次浏览 • 2016-04-22 12:46 • 来自相关话题

现在QA内部很多组都是用Flask做一些web开发,或者接口开发,然而很多应用可能直接使用Python 运行,这个存在很大的性能问题(之前做的AB测试数据)。下面介绍怎么使用Flask + gunicorn + nginx 部署一个Flask应用,实际上网上介绍这个的更多,但是大多偏于复杂,操作难度大。
 
一、准备好Flask应用
就是自己开发的Flask应用,可以使用Python跑起来即可,假设运行方式是python run_demo_flask,使用的端口是8080。
 
二、使用gunicorn
首先安装gunicorn,很简单,没有安装过的,直接:pip install gunicorn
pip install gevent使用gunicorn运行Flask:gunicorn --worker-class=gevent -w 4 -t 30 -b ip:8080 run_demo_flask:app注意:将ip换成你部署的服务器的IP地址,app为flask的实例对象名字。
 
三、使用nginx代理
 
可以将下面的配置放入到nginx的vhost目录,(名字为xxxx.conf,必须以conf结尾),然后重启nginx即可。
重启方式nginx -t # 测试下配置是否正确
service nginx restart # 如果正确就重启3.1 如果有域名,nginx 配置文件如下erver {
listen 80;
server_name xxx.163-inc.com;
client_max_body_size 128M;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}访问方式:http://xxx.163-inc.com

3.2 如果没有域名server {
listen 8081;
server_name ip;
client_max_body_size 128M;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
listen的端口换一个没有使用的端口,然后proxy_pass传入8080(flask_demo的端口)
访问方式:http://ip:8081
 
重启nginx即可完毕。 查看全部
现在QA内部很多组都是用Flask做一些web开发,或者接口开发,然而很多应用可能直接使用Python 运行,这个存在很大的性能问题(之前做的AB测试数据)。下面介绍怎么使用Flask + gunicorn + nginx 部署一个Flask应用,实际上网上介绍这个的更多,但是大多偏于复杂,操作难度大。
 
一、准备好Flask应用
就是自己开发的Flask应用,可以使用Python跑起来即可,假设运行方式是python run_demo_flask,使用的端口是8080。
 
二、使用gunicorn
首先安装gunicorn,很简单,没有安装过的,直接:
pip install gunicorn
pip install gevent
使用gunicorn运行Flask:
gunicorn --worker-class=gevent -w 4 -t 30 -b ip:8080 run_demo_flask:app
注意:将ip换成你部署的服务器的IP地址,app为flask的实例对象名字。
 
三、使用nginx代理
 
可以将下面的配置放入到nginx的vhost目录,(名字为xxxx.conf,必须以conf结尾),然后重启nginx即可。
重启方式
nginx -t  # 测试下配置是否正确
service nginx restart # 如果正确就重启
3.1 如果有域名,nginx 配置文件如下
erver {
listen 80;
server_name xxx.163-inc.com;
client_max_body_size 128M;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
访问方式:http://xxx.163-inc.com

3.2 如果没有域名
server {
listen 8081;
server_name ip;
client_max_body_size 128M;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

listen的端口换一个没有使用的端口,然后proxy_pass传入8080(flask_demo的端口)
访问方式:http://ip:8081
 
重启nginx即可完毕。

Java模拟登录微信公众平台,主动推送图文消息给用户

atool 发表了文章 • 0 个评论 • 1458 次浏览 • 2016-04-22 11:37 • 来自相关话题

@2013-11-25,对博文进行说明,由于2013年10月底,微信公众平台界面完全改版,所以本博文的所有代码几乎全部不能使用,不过有网友对本博的代码进行修改并授权于我共享给大家,因此大家可以去看博文《【微信公众平台改版后】Java模拟登录微信平台,主动推送消息给用户》,本博文的思路,大家也可以看看进行参考。

很早之前,在博客中发表了关于使用java开发微信公众号接口的程序代码,详细见《微信公众号消息接口开发——Java Servlet开发》,例外利用java做了小黄鸡,小i机器人的微信聊天开发,所以之前很多人问我有关于java开发微信接口的东西~

除此之外,更重要的是:很多人还问我关于微信主动推送消息给用户的问题,我所给出的所有答案都是:微信官方没有给出主动推送的api,所有采用程序记录用户微信id,然后模拟微信接口的请求数据,去请求微信接口中设置的url,这些方法都是不可行的~

不过,要实现主动推送不是不可能的,最简单的一个思路就是使用java模拟登录微信公众平台,然后推送消息消息给用户,不过这种方式有推送限制。

由于问的人比较多,决定把代码放出来,代码还未整理,里面有解析数据可以用正则表达式替换也没做,有需要的可以自己在此基础上修改。如果你觉得有用,并帮助了你,感谢你对我的赞助和支持。
public boolean msgSend(MsgForm form, MsgType type) {
try {
if (!this.isLogin) {
this._login();
}
if (this.isLogin) {
form.setToken(this.token);
PostMethod post = new PostMethod(POST_MSG);
post.setRequestHeader(USER_AGENT_H, USER_AGENT);
post.setRequestHeader(REFERER_H, INDEX_URL);
post.setRequestHeader("Cookie", this.cookiestr);
NameValuePair[] params = null;
Part[] parts = null;
switch (type) {
case TEXT:

parts = new Part[]{
new StringPart("content", form.getContent(),
"UTF-8"),
new StringPart("type", form.getType()),
new StringPart("error", form.getError()),
new StringPart("needcomment", form.getNeedcomment()),
new StringPart("groupid", form.getGroupid()),
new StringPart("sex", form.getSex()),
new StringPart("country", form.getCountry()),
new StringPart("province", form.getProvince()),
new StringPart("city", form.getCity()),
new StringPart("token", form.getToken()),
new StringPart("ajax", form.getAjax()),
new StringPart("t", "ajax-response")};
break;
case IMAGE_TEXT:
parts = new Part[]{
new StringPart("content", form.getContent(),
"UTF-8"),
new StringPart("type", form.getType()),
new StringPart("error", form.getError()),
new StringPart("needcomment", form.getNeedcomment()),
new StringPart("groupid", form.getGroupid()),
new StringPart("sex", form.getSex()),
new StringPart("country", form.getCountry()),
new StringPart("province", form.getProvince()),
new StringPart("city", form.getCity()),
new StringPart("token", form.getToken()),
new StringPart("ajax", form.getAjax()),
new StringPart("t", "ajax-response")};
break;
default:
parts = new Part[]{
new StringPart("content", form.getContent(),
"UTF-8"),
new StringPart("type", form.getType()),
new StringPart("error", form.getError()),
new StringPart("needcomment", form.getNeedcomment()),
new StringPart("groupid", form.getGroupid()),
new StringPart("sex", form.getSex()),
new StringPart("country", form.getCountry()),
new StringPart("province", form.getProvince()),
new StringPart("city", form.getCity()),
new StringPart("token", form.getToken()),
new StringPart("ajax", form.getAjax()),
new StringPart("t", "ajax-response")};
break;
}
RequestEntity entity = new MultipartRequestEntity(parts,
post.getParams());
post.setRequestEntity(entity);
int status;
status = client.executeMethod(post);
if (status == HttpStatus.SC_OK) {
String text = post.getResponseBodyAsString();
try {
MsgJson ret = JSON.parseObject(text, MsgJson.class);
this.msgSendCode = ret.getRet();
switch (this.msgSendCode) {
case 0:
this.msgSendMsg = "发送成功";
return true;
case -2:
this.msgSendMsg = "参数错误,请仔细检查";
return false;
case 64004:
this.msgSendMsg = "今天的群发数量已到,无法群发";
return false;
case -20000:
this.msgSendMsg = "请求被禁止,请仔细检查token是否合法";
return false;
default:
this.msgSendMsg = "未知错误!";
return false;
}
} catch (Exception e) {
String info = "【群发信息失败】【解析json错误】" + e.getMessage()
+ "
【文本:】
" + text;
System.err.println(info);
log.debug(info);
log.info(info);
return false;
}
}
}
} catch (Exception e) {
String info = "【群发信息失败】" + e.getMessage();
System.err.println(info);
log.debug(info);
log.info(info);
return false;
}
return false;
} 查看全部
@2013-11-25,对博文进行说明,由于2013年10月底,微信公众平台界面完全改版,所以本博文的所有代码几乎全部不能使用,不过有网友对本博的代码进行修改并授权于我共享给大家,因此大家可以去看博文《【微信公众平台改版后】Java模拟登录微信平台,主动推送消息给用户》,本博文的思路,大家也可以看看进行参考。

很早之前,在博客中发表了关于使用java开发微信公众号接口的程序代码,详细见《微信公众号消息接口开发——Java Servlet开发》,例外利用java做了小黄鸡,小i机器人的微信聊天开发,所以之前很多人问我有关于java开发微信接口的东西~

除此之外,更重要的是:很多人还问我关于微信主动推送消息给用户的问题,我所给出的所有答案都是:微信官方没有给出主动推送的api,所有采用程序记录用户微信id,然后模拟微信接口的请求数据,去请求微信接口中设置的url,这些方法都是不可行的~

不过,要实现主动推送不是不可能的,最简单的一个思路就是使用java模拟登录微信公众平台,然后推送消息消息给用户,不过这种方式有推送限制。

由于问的人比较多,决定把代码放出来,代码还未整理,里面有解析数据可以用正则表达式替换也没做,有需要的可以自己在此基础上修改。如果你觉得有用,并帮助了你,感谢你对我的赞助和支持。
public boolean msgSend(MsgForm form, MsgType type) {
try {
if (!this.isLogin) {
this._login();
}
if (this.isLogin) {
form.setToken(this.token);
PostMethod post = new PostMethod(POST_MSG);
post.setRequestHeader(USER_AGENT_H, USER_AGENT);
post.setRequestHeader(REFERER_H, INDEX_URL);
post.setRequestHeader("Cookie", this.cookiestr);
NameValuePair[] params = null;
Part[] parts = null;
switch (type) {
case TEXT:

parts = new Part[]{
new StringPart("content", form.getContent(),
"UTF-8"),
new StringPart("type", form.getType()),
new StringPart("error", form.getError()),
new StringPart("needcomment", form.getNeedcomment()),
new StringPart("groupid", form.getGroupid()),
new StringPart("sex", form.getSex()),
new StringPart("country", form.getCountry()),
new StringPart("province", form.getProvince()),
new StringPart("city", form.getCity()),
new StringPart("token", form.getToken()),
new StringPart("ajax", form.getAjax()),
new StringPart("t", "ajax-response")};
break;
case IMAGE_TEXT:
parts = new Part[]{
new StringPart("content", form.getContent(),
"UTF-8"),
new StringPart("type", form.getType()),
new StringPart("error", form.getError()),
new StringPart("needcomment", form.getNeedcomment()),
new StringPart("groupid", form.getGroupid()),
new StringPart("sex", form.getSex()),
new StringPart("country", form.getCountry()),
new StringPart("province", form.getProvince()),
new StringPart("city", form.getCity()),
new StringPart("token", form.getToken()),
new StringPart("ajax", form.getAjax()),
new StringPart("t", "ajax-response")};
break;
default:
parts = new Part[]{
new StringPart("content", form.getContent(),
"UTF-8"),
new StringPart("type", form.getType()),
new StringPart("error", form.getError()),
new StringPart("needcomment", form.getNeedcomment()),
new StringPart("groupid", form.getGroupid()),
new StringPart("sex", form.getSex()),
new StringPart("country", form.getCountry()),
new StringPart("province", form.getProvince()),
new StringPart("city", form.getCity()),
new StringPart("token", form.getToken()),
new StringPart("ajax", form.getAjax()),
new StringPart("t", "ajax-response")};
break;
}
RequestEntity entity = new MultipartRequestEntity(parts,
post.getParams());
post.setRequestEntity(entity);
int status;
status = client.executeMethod(post);
if (status == HttpStatus.SC_OK) {
String text = post.getResponseBodyAsString();
try {
MsgJson ret = JSON.parseObject(text, MsgJson.class);
this.msgSendCode = ret.getRet();
switch (this.msgSendCode) {
case 0:
this.msgSendMsg = "发送成功";
return true;
case -2:
this.msgSendMsg = "参数错误,请仔细检查";
return false;
case 64004:
this.msgSendMsg = "今天的群发数量已到,无法群发";
return false;
case -20000:
this.msgSendMsg = "请求被禁止,请仔细检查token是否合法";
return false;
default:
this.msgSendMsg = "未知错误!";
return false;
}
} catch (Exception e) {
String info = "【群发信息失败】【解析json错误】" + e.getMessage()
+ "
【文本:】
" + text;
System.err.println(info);
log.debug(info);
log.info(info);
return false;
}
}
}
} catch (Exception e) {
String info = "【群发信息失败】" + e.getMessage();
System.err.println(info);
log.debug(info);
log.info(info);
return false;
}
return false;
}