置頂隨筆
#
摘要: 項(xiàng)目地址: http://github.com/adoggie/TCE 從12年的時(shí)候開始想做一個(gè)rpc的東東,這些年來陸陸續(xù)續(xù)往里面增加不同的功能、特點(diǎn)。
tce是一個(gè) 全棧的東西,并不是 protocalbuf,或者接近 thrift。 支持語言: csharp,python,java,objc,javascript,actionscript,c++,我想這些夠了。
閱讀全文
摘要: 有問題的c++通信代碼的識(shí)別,希望寫c++的碼農(nóng)不要犯同樣的錯(cuò) 閱讀全文
近日獲得一份微信營(yíng)銷系統(tǒng)的代碼,看其功能比較豐富,便開始窺其代碼的實(shí)現(xiàn)。為了將整個(gè)業(yè)務(wù)系統(tǒng)跑起來,還真的花了不少時(shí)間琢磨,幸好不負(fù)我的幾十年功力,終于將運(yùn)營(yíng)環(huán)境和開發(fā)環(huán)境搭建成功,并將系統(tǒng)的授權(quán)代碼全部剔除(軟件廠商控制使用授權(quán))。 準(zhǔn)備條件: 1. 互聯(lián)網(wǎng)服務(wù)器(必須開啟80,443端口) 2. 申請(qǐng)域名,且綁定到服務(wù)器 3. 微信公眾號(hào)申請(qǐng),并通過微信認(rèn)證(300人民幣) 先上系統(tǒng)部署圖 : 環(huán)境配置.jpg) 幾個(gè)部件需要介紹一下: 1. xampp : 開發(fā)php的套件,包含了apache,php,mysql,用起來很簡(jiǎn)單,不過我是部署在linux和mac 上,要留意的是文件目錄訪問權(quán)限的問題,mac下 所有的服務(wù)進(jìn)程跑在root用戶下; 2. phpstrom: 開發(fā)php的ide,出自jetbrains(我個(gè)人理解是目前開發(fā)工具最牛逼的公司)。 管理數(shù)據(jù)庫(kù)推薦 DataGrip 軟件。 3. xdebug : 這個(gè)東西是php與phpstrom的調(diào)試接口 ,apche接收到http請(qǐng)求,轉(zhuǎn)給php解釋器,php解釋器再phpStorm進(jìn)行調(diào)試互動(dòng)(建立xdebug的9000端口的tcp連接),開發(fā)者可以在phpStorm里面隨意下斷點(diǎn)。 注意: 在php.ini中需配置 ide-key:scott , 我是在nginx的轉(zhuǎn)發(fā)頭里面添加了 XDEBUG_SESSION=scott,令所有經(jīng)過 nginx 服務(wù)器的http請(qǐng)求都被轉(zhuǎn)到phpStorm中,否則無法實(shí)現(xiàn)代碼斷點(diǎn)。 4. wxDebuger: 這是微信提供的本地微信頁(yè)面調(diào)試工具,開發(fā)這可以利用winre來調(diào)試手機(jī)上的頁(yè)面,也可以脫離手機(jī),直接調(diào)試微信頁(yè)面(要調(diào)試微信的wxjssdk必須使用wxDebuger)。 5. nginx : 在公網(wǎng)服務(wù)器部署nginx作為http服務(wù)器,接收各種用戶請(qǐng)求,并將其轉(zhuǎn)發(fā)到xampp。 6. vpn : 這個(gè)是關(guān)鍵,為了實(shí)現(xiàn)本地開發(fā)調(diào)試的目的,我在公網(wǎng)服務(wù)器上部署了openvpn,并在mac開發(fā)機(jī)上部署了xampp,phpstorm等,并安裝vpn客戶端 Tunnelblick,其自動(dòng)撥號(hào)到公網(wǎng)服務(wù)器,獲得地址10.8.0.6,nginx將http請(qǐng)求轉(zhuǎn)發(fā)到了我本地的開發(fā)機(jī)器上,這樣我可以很方便的進(jìn)行遠(yuǎn)程和本地調(diào)試了。 主要的功能描述: 1. 手機(jī)、瀏覽器、調(diào)試器 發(fā)起的http請(qǐng)求到達(dá)公網(wǎng)服務(wù)器,nginx通過vpn轉(zhuǎn)發(fā)到本地開發(fā)機(jī),開發(fā)者在phpstorm中斷點(diǎn)調(diào)試代碼,并將處理結(jié)果按原路返回。 2. 微信服務(wù)器的主要作用是獲取 粉絲信息、oauth認(rèn)證回調(diào)、服務(wù)器鑒權(quán)等功能 , HTTP(302)是 oauth的靈魂 。 3. 這種配置架構(gòu)很靈活的可以將開發(fā)模式切換到部署模式,只需要將xampp部署到公網(wǎng)服務(wù)器,并在 nginx的反向代理指到本地xampp服務(wù)即可。 附錄 nginx.conf server { listen 80; server_name wx.xxxx.com www.xxxx.com; proxy_set_header X-real-ip $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / { proxy_pass http://10.8.0.6:8081; proxy_set_header Cookie "$http_cookie;XDEBUG_SESSION=scott"; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-real-ip $remote_addr; } }
摘要: 6.x 版本系統(tǒng)自帶python 2.6,升級(jí)2.7的方式網(wǎng)上有很多版本,本人試用下來覺得諸多不便。
工作項(xiàng)目中越來越多的開發(fā)特性必須要求工作在py2.7版本中,例如: django 1.7+已經(jīng)不支持 py2.6.x了; pyBox2d也不支持。
這次選擇的最新版本 python 2.7.11 閱讀全文
訪問sf,記錄下一下代碼 (注冊(cè)sf的app,登記 callback-url,執(zhí)行sql查詢) #coding:utf-8 __author__ = 'scott' import imp imp.load_source('init','../init_script.py') import urllib2,urllib,json,sys,os import traceback,threading,time,struct,os,os.path,shutil,distutils.dir_util,array,base64,zlib,struct,binascii import datetime from libs.python.lemon import webapi callback = 'http://localhost:8002/oauth' client_id = '3MVG9ZL0ppGP5UrC_wQ8U02mOhowPKwjeaaLsWZ3BcYYVqiSsy1rL_D2h6qG.rGPnb_j6IcgLHPdhmvomzDFj' client_secret = '9046731979xxxxxxx'
def accessToken(request,code,state): url = 'https://login.salesforce.com/services/oauth2/token' data = { 'grant_type':'authorization_code', 'code':code, 'client_id':client_id, 'client_secret':client_secret, 'redirect_uri':callback } result = '' try: result = urllib2.urlopen(url,urllib.urlencode(data) ) except: traceback.print_exc() result = result.read() return json.loads( result )
def oauth(request): cr = webapi.SuccCallReturn() code = webapi.GET(request,'code','') state = webapi.GET(request,'state','') cr.result=[code,state] token = accessToken(request,code,state) cr.result.append(token) print token try: sqlExecute(token['access_token'],token['instance_url']) except: traceback.print_exc() return cr.httpResponse()
import cookielib
# -H "Authorization: OAuth token" -H "X-PrettyPrint:1" " def sqlExecute(token,url_host): httpHandler = urllib2.HTTPHandler(debuglevel=1) httpsHandler = urllib2.HTTPSHandler(debuglevel=1) opener = urllib2.build_opener(httpHandler, httpsHandler) urllib2.install_opener(opener) sf_cmd_query="%s/services/data/v20.0/query/?%s"%(url_host, urllib.urlencode({'q':'select count() from account'})) headers = { 'Authorization':'OAuth %s'%token, 'X-PrettyPrint':1 } httpReq = urllib2.Request( sf_cmd_query,headers=headers ) r = opener.open(httpReq).read() print r pass
url1 = """https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id=%s&redirect_uri=%s&state=first"""%(client_id,callback)
def launchBrowserForOAuth(): import webbrowser webbrowser.open(url1)
if __name__ == '__main__': launchBrowserForOAuth()
python內(nèi)部數(shù)據(jù)容器有dict和list兩種 ,工作中最常用的方式是定義一些數(shù)據(jù)結(jié)構(gòu)(數(shù)據(jù)即代碼),例如:
1 frog={'name':'scott', 2 'age':2, 3 'parts':{ 4 'eye':'green','leg':85 5 }, 6 ''friend":['moee','wee'], 7 "hometown":'affica' 8 } frog對(duì)象定義了小動(dòng)物的某些屬性,訪問frog對(duì)象屬性時(shí),通過 dict,list的取值方法進(jìn)行訪問,例如: print frog['name'] print frog['friend'][0] 有時(shí)覺得這種表達(dá)方式太原始了,需要改進(jìn),最好是以 '.'方式訪問對(duì)象屬性,例如: print frog.name 代碼來開始和結(jié)束吧, class _x 1 class _x: 2 """ 3 從簡(jiǎn)單數(shù)據(jù)類型轉(zhuǎn)換成python對(duì)象 4 5 p = _x({'name':'boob','body':{'color':'black'},'toys':[1,2,3,],'age':100}) 6 print p['toys'][1] 7 print len(p.toys) 8 print p.body.colors 9 """ 10 def __init__(self,primitive): 11 self.data = primitive 12 13 def __getattr__(self, item): 14 value = self.data.get(item,None) 15 if type(value) == dict: 16 value = _x(value) 17 return value 18 19 def __len__(self): 20 return len(self.data) 21 22 def __str__(self): 23 return str(self.data) 24 25 def __getitem__(self, item): 26 value = None 27 if type(self.data) in (list,tuple): 28 value = self.data[item] 29 if type(value) in (dict,list,tuple): 30 value = _x(value) 31 elif type(self.data) == dict: 32 value = self.__getattr__(item) 33 return value
相關(guān)技術(shù): haproxy_keepalived_nginx_uwsgi_gevent_django
之前部署django一直采用 apache + mod_wsgi,用得倒也沒啥問題,看到越來越多的人采用nginx部署,所以也嘗試了一下,結(jié)果很讓人欣喜。
nginx夠小夠簡(jiǎn)潔,編譯、配置相當(dāng)簡(jiǎn)單,但要知道她僅僅是個(gè)靜態(tài)webserver,動(dòng)態(tài)功能需要搭配相應(yīng)的cgi來實(shí)現(xiàn); uwsgi是個(gè)啥東西,看其官方文檔還真寫的相當(dāng)詳細(xì),功能很豐富,但我的需求可能只會(huì)使用其30%的功能; uwsgi可以認(rèn)為是python代碼運(yùn)行的loader,或者是容器(container),這有點(diǎn)像java的container(resin,tomcat)。看了其配置文檔,很是驚喜,其不僅可以配置為多進(jìn)程+多線程模式,也可以配置為單進(jìn)程+多線程模式,并能保持高并發(fā)高銷率,非常感興趣。 一直以來自己總在尋找一種 高效、靈活的django的應(yīng)用容器。 apache默認(rèn)都是多進(jìn)程模式,http又是無狀態(tài)的,不同的請(qǐng)求被分派到不同的進(jìn)程處理,request處理都是隔離的。多進(jìn)程帶來的問題是高昂的系統(tǒng)開銷(apache也支持多線程處理)。 這種隔離又帶來了諸多不便,request之間不能共享狀態(tài)、數(shù)據(jù)和協(xié)作,不能很好的完成與外部系統(tǒng)的協(xié)同工作(例如request共享同一個(gè)服務(wù)器的socket連接或者訪問控制某個(gè)rs232端口) 所以很想有種類似java的應(yīng)用容器這樣的東東。 接觸了gevent,其核心是io異步分派,單線程模擬多協(xié)程來對(duì)應(yīng)用層多任務(wù)的支持,幾近瘋狂io效率得到了我的認(rèn)可。ps:八過smp系統(tǒng)就應(yīng)該啟動(dòng)多個(gè)gevent服務(wù),不然其他核心數(shù)都浪費(fèi)了。 采用gevent+django的模式搭建了自己得app容器,也跑了幾個(gè)項(xiàng)目,總體效果還是可以。 nginx+uwsgi+django 的配合開始應(yīng)用到新項(xiàng)目中
上海交通違章查詢網(wǎng)站: http://www.shjtaq.com/Server1/dzjc_new.asp 驗(yàn)證碼圖片獲取地址: http://www.shjtaq.com/Server1/validatecode.asp?m=2304.046
服務(wù)器通過頁(yè)面請(qǐng)求的session-id來區(qū)分之后提交的驗(yàn)證碼。 第一次請(qǐng)求查詢頁(yè)面時(shí),服務(wù)器將訪問session(cookie)傳到客戶端,之后的查詢和驗(yàn)證碼獲取時(shí)客戶端攜帶之前的cookie傳送到服務(wù)器,服務(wù)器端保存著當(dāng)前 session-id與驗(yàn)證碼 的對(duì)應(yīng)關(guān)系。
查詢返回記錄可通過 xpath或者 beautifulsoup進(jìn)行解析
程序使用python完成,也是個(gè)簡(jiǎn)單的小爬蟲,scrapy 之類的沒必要使用了,gevent完成異步通信。
交通網(wǎng)的驗(yàn)證碼生成還是比較簡(jiǎn)單,做自動(dòng)識(shí)別可找?guī)讉€(gè)簡(jiǎn)單的圖形識(shí)別程序即可。 如若不行,則人工輸入嘍
開始抓yixun.com的商品信息,開始很開心,但一下子來了問題。http請(qǐng)求回來的商品分類條目用<a href=>, 但這個(gè)href不能直接使用,因?yàn)轫?yè)面加載之后會(huì)啟動(dòng)js程序(一般都是jquery)對(duì)頁(yè)面element進(jìn)行配置和處理,例如:設(shè)置風(fēng)格、事件等等。
yixun玩了個(gè)防頁(yè)面過期的小技巧: >每個(gè)請(qǐng)求page在server都會(huì)產(chǎn)生一個(gè)有效期變量XY(具體算法不詳), >如果獲取商品<a>直接請(qǐng)求,server將返回失敗,因?yàn)?lt;a href>并未包含XY >page加載完成之后js代碼設(shè)置<a>被點(diǎn)擊時(shí)觸發(fā)事件E,E將XY添加到<a href>內(nèi) >然后可以正確請(qǐng)求了 易迅防止請(qǐng)求頁(yè)面過期,在主頁(yè)中設(shè)置了一下參數(shù): <script type="text/javascript"> window.yPageId = '17384560'; window.yPageLevel = '2';</script>
在頁(yè)面內(nèi)容中顯示 <a ytag="40037" target="_blank">路由器</a> 注意: 返回的html就是如此
但如果用戶點(diǎn)擊(左鍵或者右鍵)此 node對(duì)象時(shí),js代碼會(huì)動(dòng)態(tài)插入一個(gè)YTAG的變量
未點(diǎn)擊: <a ytag="40037" target="_blank">路由器</a> 點(diǎn)擊: <a ytag="40037" target="_blank">路由器</a>
變量生成方式在這個(gè)js中實(shí)現(xiàn): 此js 使用了jquery,頁(yè)面完成加載之后,將配置頁(yè)面元素的onclick行為,如果點(diǎn)擊了頁(yè)面元素,將YTAG屬性加入到商品<a href=""/>中去
js代碼凌亂可以使用: 進(jìn)行格式化觀察
js代碼: G.header.search = { init: function() { G.header.search.event(); G.header.search.setInputStyle(); G.header.search.autoComplete(); },G.header.search.init();query: function() { var input = $("#q_show"), v = $.trim(input.val()), c = $("#cate_show").val(), ret = true, href = input.attr("_href"); if (v === G.header._Q_SHOW_DEF_TEXT && href) { window.location.href = href; ret = false; } else if (v === "" || v === G.header._Q_SHOW_DEF_TEXT) { if (!c || (c && c == "")) { input.focus(); ret = false; } } if ($('#q_show').parents("form").find('input[name="YTAG"]').length === 0) { var ytag = $('#q_show').parents("form").find('input[type="submit"]').attr("ytag"); var YTAG = (window.yPageLevel || 0) + '.' + (window.yPageId || 0) + ytag; $('#q_show').parents("form").append($('<input type="hidden" name="YTAG" value="' + YTAG + '" />')); } return ret; }
程序定義了G.header.search對(duì)象,并進(jìn)行初始化init() ,query()是用戶點(diǎn)擊查詢時(shí)觸發(fā)使用 init()內(nèi)部配置了query函數(shù),用于鼠標(biāo)點(diǎn)擊時(shí)候生成YTAG屬性 看代碼就很簡(jiǎn)單了
YTAG生成方式就是 window.yPageLevel+'.'+window.yPageId + <a ytag="40037"> 這樣一個(gè)商品條目的href就獲得了
tkinter工作在主線程,而gevent是單線程工作,如何整合在一起? 瞅到一段代碼,迅速收藏 1 import gevent 2 from gevent import socket 3 import Tkinter as tk 4 5 class SockLoop(object): 6 def __init__(self, callback): 7 self.callback = callback 8 9 def __call__(self, sock, client): 10 while 1: 11 mes = sock.recv(256) 12 ret = self.callback(client, mes) 13 if ret is not None: 14 sock.send(ret) 15 16 def socket_server(port, callback): 17 ssock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) 18 ssock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 19 ssock.bind(('', port)) 20 ssock.listen(5) 21 22 while 1: 23 sock, client = ssock.accept() 24 gevent.spawn(callback, sock, client) 25 26 class App(object): 27 def __init__(self, root): 28 self.greenlet = None 29 self.root = root 30 self._build_window(root) 31 self.root.after(100, self._connect) 32 33 def add_text(self, text): 34 cleaned_string = text.replace('\r', '') 35 self.text.insert(tk.END, cleaned_string) 36 37 def quit(self): 38 self.root.quit() 39 40 def _build_window(self, root): 41 self.frame = tk.Frame(root) 42 self.text = tk.Text(self.frame) 43 self.quit_button = tk.Button(self.frame, text="Quit", command=self.quit) 44 self.text.pack() 45 self.quit_button.pack() 46 self.frame.pack() 47 48 def _connect(self): 49 self.greenlet = gevent.spawn( 50 socket_server, 51 8080, 52 SockLoop(lambda cl, txt: self.add_text("%s: %s" % (cl, txt)))) 53 self.gevent_loop_step() 54 55 def gevent_loop_step(self): 56 gevent.sleep() 57 self.root.after_idle(self.gevent_loop_step) 58 59 60 if __name__ == '__main__': 61 root = tk.Tk() 62 app = App(root) 63 root.mainloop()
俺不是果粉,但開發(fā)必須mac 參加的開發(fā)者大會(huì),老外沒一個(gè)不是mac的,也的確如此,mac是開發(fā)神器,雖然貴點(diǎn),但還是很值,對(duì)得起他的身價(jià) 。 這是一種態(tài)度,價(jià)值觀世界觀的體現(xiàn) linux+windows的完美結(jié)合,不!! ui遠(yuǎn)超windows
14.5k mac pro 15 retina 8G 內(nèi)存 250 G ssd ,都配置差了點(diǎn),但目前夠了,有錢了再買臺(tái)高配的,然后imac,還有那個(gè)外星桶的工作站
酷斃!
寫代碼,寫好代碼其實(shí)并不難,但如果要做好文檔,能完整闡述清楚自己的構(gòu)思、想法和邏輯結(jié)構(gòu),這比較難,自己也缺少這方面的耐心。 很多opensource的代碼根本不需要文檔也能一目了然,這是一種定力 多年前的項(xiàng)目中使用到python和ffmpeg, 網(wǎng)絡(luò)上搜索了一下,均不能滿足自己的要求。ffmpeg的python綁定提供的均是文件級(jí)的訪問控制,也就是說沒有暴露更多的可控接口來用。 所以還是一切都自己來做 ffmpeg采用0.81版本以上,當(dāng)時(shí)發(fā)現(xiàn)mov文件在0.71以下無法正常解碼,到0.81則解決了此問題。 python包裝ffmpeg的方式很多,最好的可能就是swig,但太煩了,最后選擇ctypes來訪問ffmpeg接口。 如果直接使用ffmpeg的api接口也不太合適,因?yàn)橐┞逗芏鄁fmpeg的接口、數(shù)據(jù)類型、常數(shù)定義等。 所以我是這么處理: 1. 編寫一個(gè)功能動(dòng)態(tài)庫(kù)來包裝ffmpeg,提供基本的業(yè)務(wù)功能 ,屏蔽ffmpeg細(xì)節(jié),這里叫ffmpeg_media_codec.dll 2. 用ctypes包裝此ffmpeg_media_codec.dll,這里是ffmpeg.py 3. 業(yè)務(wù)代碼使用ffmpeg.py提供的接口訪問、解碼多媒體文件 代碼: http://sw2us.com/static/projects/py-ffmpeg/ffmpeg_media_codec.dll 暴露的c接口 1 ffmpeg lib interface list: 2 =========================== 4 typedef unsigned char StreamByte_t; 6 struct MediaStreamInfo_t{ 7 int codec_type; 8 int codec_id; 9 int width; 10 int height; 11 int gopsize; 12 int pixfmt; 13 int tb_num; 14 int tb_den; 15 int bitrate; 16 int frame_number; 17 int videostream; //視頻流編號(hào) 18 }; 19 20 struct MediaVideoFrame_t{ 21 StreamByte_t * rgb24; 22 size_t size; 23 int width; 24 int height; 25 unsigned int sequence; //控制播放順序 26 unsigned int duration; //播放時(shí)間 27 }; 28 29 struct MediaPacket_t{ 30 StreamByte_t* data; 31 size_t size; 32 AVPacket * pkt; 33 int stream; //流編號(hào) 34 int dts; 35 int pts; 36 size_t sequence; 37 size_t duration; 39 }; 40 41 struct MediaFormatContext_t; 42 43 //解碼器 44 struct MediaCodecContext_t{ 45 AVCodecContext * codecCtx; //AVCodecContext* 46 AVCodec * codec; 47 int stream; //流編號(hào) 48 AVFrame * rgbframe24; // 49 AVFrame* frame; // 50 StreamByte_t* buffer; 51 size_t bufsize; 52 void * user; 53 MediaStreamInfo_t si; 54 }; 55 56 struct MediaFormatContext_t{ 57 AVFormatContext * fc; //AVFormatContext* 58 MediaStreamInfo_t video; //視頻信息 60 }; 66 #ifdef __cplusplus 67 extern "C" { 68 #endif 69 70 int InitLib(); //初始化解碼庫(kù) 71 void Cleanup(); // 73 MediaCodecContext_t* InitAvCodec(MediaStreamInfo_t* si); //根據(jù)媒體類型分配解碼器對(duì)象 74 void FreeAvCodec(MediaCodecContext_t* codec); //釋放解碼器對(duì)象 76 MediaVideoFrame_t * DecodeVideoFrame(MediaCodecContext_t* ctx,MediaPacket_t* pkt); //送入媒體包進(jìn)行解碼,返回視頻幀 77 void FreeVideoFrame(MediaVideoFrame_t* frame); //釋放視頻幀 79 MediaPacket_t * AllocPacket(); //分配一個(gè)流媒體包對(duì)象(用于網(wǎng)傳) 80 void FreePacket(MediaPacket_t* pkt); //釋放流媒體包 82 MediaFormatContext_t* InitAvFormatContext(char * file); //媒體文件訪問上下文,申請(qǐng) 83 void FreeAvFormatContext(MediaFormatContext_t* ctx); //釋放 84 MediaPacket_t* ReadNextPacket(MediaFormatContext_t* ctx); //讀媒體文件一個(gè)數(shù)據(jù)包 85 void ReadReset(MediaFormatContext_t* ctx) ; //重置媒體訪問讀取位置 86 int SeekToTime(int timesec) ; //跳躍到指定時(shí)間 ffmpeg.py 包裝: 1 import ctypes 2 from ctypes import *
5 _lib = cdll.LoadLibrary('ffmpeg.dll') 6 7 _int_types = (c_int16, c_int32) 8 if hasattr(ctypes, 'c_int64'): 9 # Some builds of ctypes apparently do not have c_int64 10 # defined; it's a pretty good bet that these builds do not 11 # have 64-bit pointers. 12 _int_types += (ctypes.c_int64,) 13 for t in _int_types: 14 if sizeof(t) == sizeof(c_size_t): 15 c_ptrdiff_t = t 16 17 class c_void(Structure): 18 # c_void_p is a buggy return type, converting to int, so 19 # POINTER(None) == c_void_p is actually written as 20 # POINTER(c_void), so it can be treated as a real pointer. 21 _fields_ = [('dummy', c_int)]
26 class MediaStreamInfo_t(Structure): 27 _fields_ = [ 28 ('codec_type', c_int), 29 ('codec_id', c_int), 30 ('width', c_int), 31 ('height', c_int), 32 ('gopsize', c_int), 33 ('pixfmt', c_int), 34 ('tb_num',c_int), 35 ('tb_den',c_int), 36 ('bitrate',c_int), 37 ('frame_number',c_int), 38 ('videostream',c_int), 39 ('duration',c_int), 40 ('extr',POINTER(c_char)), #解碼器 額外hash表數(shù)據(jù) 41 ('extrsize',c_int), 42 ] 43 44 class MediaVideoFrame_t(Structure): 45 _fields_=[ 46 ('rgb24',POINTER(c_char)), 47 ('size',c_uint), 48 ('width',c_int), 49 ('height',c_int), 50 ('sequence',c_uint), 51 ('duration',c_uint) 52 ] 53 54 class MediaPacket_t(Structure): 55 _fields_=[ 56 ('data',POINTER(c_char)), 57 ('size',c_uint), 58 ('pkt',c_char_p), 59 ('stream',c_int), 60 ('dts',c_int), 61 ('pts',c_int), 62 ('sequence',c_uint), 63 ('duration',c_uint) 64 ] 65 66 67 class MediaCodecContext_t(Structure): 68 _fields_=[ 69 ('codecCtx',c_char_p), 70 ('codec',c_char_p), 71 ('stream',c_int), 72 ('rgbframe24',c_char_p), 73 ('frame',c_char_p), 74 ('buffer',c_char_p), 75 ('bufsize',c_uint), 76 ('user',c_char_p), 77 ('si',MediaStreamInfo_t) 78 ] 79 80 class MediaFormatContext_t(Structure): 81 _fields_=[ 82 ('fc',c_char_p), 83 ('video',MediaStreamInfo_t) 84 ] 85 86 InitAvCodec = _lib.InitAvCodec 87 InitAvCodec.restype = POINTER(MediaCodecContext_t) 88 InitAvCodec.argtypes = [POINTER(MediaStreamInfo_t)] 89 90 91 FreeAvCodec = _lib.FreeAvCodec 92 FreeAvCodec.restype = None 93 FreeAvCodec.argtypes = [POINTER(MediaCodecContext_t)] 96 DecodeVideoFrame = _lib.DecodeVideoFrame 97 DecodeVideoFrame.restype = POINTER(MediaVideoFrame_t) 98 DecodeVideoFrame.argtypes = [POINTER(MediaCodecContext_t),POINTER(MediaPacket_t)] 100 FreeVideoFrame = _lib.FreeVideoFrame 101 FreeVideoFrame.restype = None 102 FreeVideoFrame.argtypes = [POINTER(MediaVideoFrame_t)] 104 AllocPacket = _lib.AllocPacket 105 AllocPacket.restype = POINTER(MediaPacket_t) 106 AllocPacket.argtypes = [] 109 FreePacket = _lib.FreePacket 110 FreePacket.restype = None 111 FreePacket.argtypes = [POINTER(MediaPacket_t),c_int] 113 InitAvFormatContext = _lib.InitAvFormatContext 114 InitAvFormatContext.restype = POINTER(MediaFormatContext_t) 115 InitAvFormatContext.argtypes = [c_char_p] 117 FreeAvFormatContext = _lib.FreeAvFormatContext 118 FreeAvFormatContext.restype = None 119 FreeAvFormatContext.argtypes = [POINTER(MediaFormatContext_t)] 122 ReadNextPacket = _lib.ReadNextPacket 123 ReadNextPacket.restype = POINTER(MediaPacket_t) 124 ReadNextPacket.argtypes = [POINTER(MediaFormatContext_t)] 127 ReadReset = _lib.ReadReset 128 ReadReset.restype = None 129 ReadReset.argtypes = [POINTER(MediaFormatContext_t)] 130 131 SeekToTime = _lib.SeekToTime 132 SeekToTime.restype = c_int 133 SeekToTime.argtypes = [POINTER(MediaFormatContext_t),c_int] 134 135 FlushBuffer = _lib.FlushBuffer 136 FlushBuffer.restype =None 137 FlushBuffer.argtypes = [POINTER(MediaCodecContext_t)] 138 139 InitLib = _lib.InitLib 140 InitLib.restype =None 141 InitLib.argtypes = [] 142 143 Cleanup = _lib.Cleanup 144 Cleanup.restype =None 145 Cleanup.argtypes = [] 好了,看看如何使用這些接口 視頻文件播放: http://sw2us.com/static/projects/py-ffmpeg/test_qt.py
從事webgis及其應(yīng)用有些時(shí)日,實(shí)驗(yàn)性質(zhì)的東西一直沒有被大規(guī)模應(yīng)用,一路走來頗多辛苦 現(xiàn)將代碼放出,有興趣的朋友可看看,包括地圖數(shù)據(jù)處理編譯、地圖渲染服務(wù)程序、wms程序、tce
近一周時(shí)間都在玩p2p,本來以為實(shí)現(xiàn)很簡(jiǎn)單,但做起來實(shí)屬不易 。 Udp穿透Nat會(huì)遇到多種Nat類型: 1.FULL CORE 2. RESTRICT 3. PORT-RESTRICT 4. SYMMETRIC 1-3三種NAT實(shí)現(xiàn)穿透很簡(jiǎn)單,問題在于處理第4種類型:對(duì)等NAT SYMMETRIC NAT的工作模式區(qū)分在于內(nèi)網(wǎng)通過NAT時(shí)分配的外部端口的方式不同,這又有三種情況: 1. 端口遞增: 通常新端口號(hào)會(huì)是前一次分配端口號(hào)加1或者加固定值 2. 端口在當(dāng)前NAT最新端口的左右區(qū)間: 例如當(dāng)前NAT外網(wǎng)端口P,那新的分配端口會(huì)落在 -N < P < N 3. 隨機(jī)分配SR (這個(gè)根據(jù)當(dāng)時(shí)NAT的網(wǎng)絡(luò)情況參數(shù)等作為函數(shù)f(x)的因子決定) 這第三種分配方式,目前無解,只要任意一端存在SR,則無法穿透 當(dāng)然很多技術(shù)研究者提出了如何猜測(cè)動(dòng)態(tài)端口的方案,例如:統(tǒng)計(jì)技術(shù)的使用,服務(wù)器可對(duì)固定NAT進(jìn)行采樣分析等等。。 這個(gè)很難哦! 面對(duì)SR我直接放棄了,還真不巧,測(cè)試了3,4個(gè)網(wǎng)絡(luò)環(huán)境的NAT,居然50%是SR,50%是SYMMETRIC的1,2種類型 。 還是老實(shí)的服務(wù)器中轉(zhuǎn)把! 一些p2p資料供參考: http://114.215.178.29/static/p2p
應(yīng)用中經(jīng)常用pyCrypto 來生成用戶Token等相關(guān)信息,夠簡(jiǎn)單,所以貼代碼分享 部分代碼被關(guān)閉或者打開,使用者請(qǐng)自行調(diào)整,如果了解rsa很簡(jiǎn)單理解一下代碼 1 GCONFS={ 2 'auth_public_keyfile':'public.rsa', 3 'auth_private_keyfile':'private.rsa' 4 } 5 6 7 def encrypt_des(key,text): 8 from Crypto.Cipher import DES 9 import base64 10 from Crypto import Random 11 #iv = Random.get_random_bytes(8) 12 des = DES.new(key, DES.MODE_ECB) 13 reminder = len(text)%8 14 if reminder ==0: # pad 8 bytes 15 text+='\x08'*8 16 else: 17 text+=chr(8-reminder)* (8-reminder) 18 #text+=' '*(8-len(text)%8) 19 return des.encrypt(text) 20 #return base64.encodestring(des.encrypt(text)) 21 22 def decrypt_des(key,text): 23 from Crypto.Cipher import DES 24 import base64 25 # print key 26 des = DES.new(key, DES.MODE_ECB) 27 text = des.decrypt(text) 28 pad = ord(text[-1]) 29 if pad == '\x08': 30 return text[:-8] 31 return text[:-pad] 32 33 34 def rsa_generate(): 35 from Crypto.PublicKey import RSA 36 from Crypto import Random 37 random_generator = Random.new().read 38 key = RSA.generate(1024, random_generator) 39 40 41 #print key.publickey().encrypt('123213213123213213',20) 42 public = key.publickey().exportKey() 43 #print key.publickey().exportKey() 44 private = key.exportKey() 45 return public,private 46 47 def rsa_encrypt(key,text): 48 ''' 49 傳入私鑰key和待加密明文數(shù)據(jù)text 50 自動(dòng)生成8字節(jié)長(zhǎng)度隨機(jī)密碼P,用P將text進(jìn)行des加密生成E, 51 用私鑰key加密P生成P2 52 53 key - private key 54 text - orignal text 55 @return: [P2+E] RSA加密的des秘鑰 + 加密的密文 56 ''' 57 import uuid 58 from Crypto.PublicKey import RSA 59 deskey = hashlib.md5(uuid.uuid1().hex).hexdigest()[:8] 60 text = encrypt_des(deskey,text) 61 62 key = RSA.importKey(key) 63 r = key.encrypt(deskey,32) 64 65 return r[0]+text # 加密的key,和des加密的數(shù)據(jù) 66 67 def rsa_decrypt(key,text): 68 from Crypto.PublicKey import RSA 69 try: 70 rsa = RSA.importKey(key) 71 deskey = text[:128] 72 text = text[128:] 73 deskey = rsa.decrypt(deskey) 74 return decrypt_des(deskey,text) 75 except: 76 return '' 77 78 class Cipher: 79 def __init__(self): 80 # self.pubkey = pubkey 81 # self.privkey = privkey 82 pass 83 84 def encrypt(self,key,text): 85 return rsa_encrypt(key,text) 86 87 88 def decrypt(self,key,text): 89 return rsa_decrypt(key,text) 90 91 @staticmethod 92 def getCipher(): 93 try: 94 cip = Cipher() 95 return cip 96 except: 97 traceback.print_exc() 98 return None 99 100 def encryptToken(user): 101 ''' 102 用戶信息轉(zhuǎn)換為token 103 ''' 104 token='' 105 try: 106 d = json.dumps(user) 107 # f = open(GCONFS['auth_public_keyfile'],'r') 108 # pubkey = f.read() 109 # f.close() 110 pubkey = ENCRYPT_PUBKEY 111 # d = Cipher.getCipher().encrypt(pubkey,d) #rsa encrpyt 112 token = base64.encodestring(d).strip() 113 #print 'token size:',len(token) 114 except: 115 print traceback.format_exc() 116 token = '' 117 118 return token 119 120 def decryptToken(token): 121 user = None 122 try: 123 # f = open(GCONFS['auth_private_keyfile'],'r') 124 # privkey = f.read() 125 # f.close() 126 privkey = ENCRYPT_PRIVKEY 127 d = base64.decodestring(token) 128 # d = Cipher.getCipher().decrypt(privkey,d) #rsa decrept 129 user = json.loads(d) 130 except: 131 #print traceback.format_exc() 132 pass 133 return user
系統(tǒng)中,用戶的消息在移動(dòng)設(shè)備與接入服務(wù)器建立的Tcp長(zhǎng)連接上傳遞。這些消息包括:文本,復(fù)合文本,位置信息,音頻剪輯,圖像等等。 發(fā)送者傳送消息到平臺(tái)系統(tǒng)內(nèi)部并將消息寫入gridfs,待接收者上線時(shí)平臺(tái)將消息推送至接收者。 考慮到帶寬利用,接收者得到的消息將不包含二進(jìn)制數(shù)據(jù),例如: 音頻,圖像等等。 這要求接收者對(duì)平臺(tái)發(fā)起一次獲取消息包內(nèi)指定的音頻和圖像數(shù)據(jù)的請(qǐng)求。 移動(dòng)端向平臺(tái)請(qǐng)求二進(jìn)制數(shù)據(jù)的情況還包含 【離線文件傳送】場(chǎng)景 。 二進(jìn)制數(shù)據(jù)往往是指那些數(shù)據(jù)量比較大的對(duì)象,這些對(duì)象在移動(dòng)兩端交換時(shí),交互通道將不占用與接入服務(wù)器的連接通道,而是通過nginx傳送到平臺(tái)內(nèi)部; 同樣接收者獲取二進(jìn)制數(shù)據(jù)也是通過nginx獲取。這種請(qǐng)求是HTTP的。 這里整理的是如何在平臺(tái)部署 【負(fù)載均衡的集群的分布式的文件服務(wù)】 nginx : http服務(wù),提供反向代理和負(fù)載均衡服務(wù)(集群可用DNS或考慮LVS方案) mongodb+gridfs : 用于文件服務(wù)提供,其內(nèi)置gridfs提供了分布式,海量存儲(chǔ)的方案 gevent+webpy : nginx直接讀取gridfs是不合適的,配置了cgi才能完成特定功能,這里使用webpy,比django更輕更好用。 webpy的作用是接收到上傳和下傳文件的請(qǐng)求,讀寫gridfs文件內(nèi)容給移動(dòng)端。 gevent是高效的通信框架,雖然單線程工作,但性能非常的好; 用好gevent關(guān)鍵在與外部的io必須全部都是異步的,例如: 數(shù)據(jù)庫(kù),文件磁盤訪問等等。 mongodb對(duì)gevent已經(jīng)支持,gevent對(duì)webpy,django,psycopg2支持也相當(dāng)?shù)暮茫砸峁﹚ebservice服務(wù)那就考慮用gevent+webpy或django把,性能是杠杠的,比 apache+mod_wsgi要好很多 ,而且gevent是進(jìn)程內(nèi)的不同的HTTP REQUEST可以是共享數(shù)據(jù)的,這一點(diǎn)非常誘惑(apache+mod_wsgi的REQUEST可是隔離的哦!除非您通過redis的PUB/SUB實(shí)現(xiàn)兩個(gè)REQUEST的通信) 關(guān)注的問題: 1.下傳大文件時(shí)的處理 如果直接用nginx當(dāng)然沒有這個(gè)問題 ,但用webpy讀取文件返回HttpResponse時(shí)問題來了,總不至于讀取整個(gè)文件,然后再return。 這種方式在php有flush方法,python只能用yield來做 2.上傳大文件時(shí)的處理 當(dāng)接收到http的文件POST請(qǐng)求時(shí),文件已經(jīng)全部緩存到web服務(wù)器,如果同時(shí)幾千個(gè)文件上傳在進(jìn)行,服務(wù)器就會(huì)被擠爆,這也是很多網(wǎng)站不允許大文件上傳的緣故吧。關(guān)于這個(gè)問題,我想就需要修改一下webpy關(guān)于文件上傳的處理代碼了,將接收到的文件數(shù)據(jù)以流的形式寫入到gridfs里去作為臨時(shí)文件被緩存,等完全接收文件時(shí),才通知到handler代碼,這樣必定高效很多(新的問題又來了,會(huì)不會(huì)把gridfs搞爆掉! 處理時(shí)考慮延時(shí)緩存提交gridfs把)。 BUF_SIZE = 262144 class download: def GET(self): file_name = 'file_name' file_path = os.path.join('file_path', file_name) f = None try: f = open(file_path, "rb") webpy.header('Content-Type','application/octet-stream') webpy.header('Content-disposition', 'attachment; filename=%s.dat' % file_name) while True: c = f.read(BUF_SIZE) if c: yield c else: break except Exception, e: print e yield 'Error' finally: if f: f.close()
links: http://api.mongodb.org/python http://webpy.org/cookbook/storeupload.zh-cn http://webpy.org/cookbook/streaming_large_files http://gevent.org 下份代碼 demo很值得看哦 gevent 1.0 由libev 替換了libevent
摘要: 貼代碼 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 #--coding:utf-8-- 2 3 ... 閱讀全文
多樣的文本消息 ----------------- struct MimeText_t{ int type; string text; }; MimeText_t 可以包含普通的文本、圖像和音頻文件的id 圖像和音頻數(shù)據(jù)發(fā)送到服務(wù)器,服務(wù)器并不直接將數(shù)據(jù)發(fā)送到接收者,而是發(fā)送 音頻和圖像的描述uri信息 接收者解釋json,顯示text文本,讀取emoticon編號(hào),顯示表情圖片; image,audio則顯示占位(如果當(dāng)前wifi可用,則自己自動(dòng)加載image和audio資源) ,如果非wifi信號(hào)則待用戶點(diǎn)擊此占位,然后從服務(wù)器請(qǐng)求image和audio資源到本地。 文本描述: 字體大小,顏色,文本link,表情符號(hào) 文本用json組織 , { set:[ text:{text:'this is',bg-color:#ff0000,color:#ffffff,font-name:'arial',font-size:20,bold:true,italic:true}, text:{text:'shanghai',color:#ff0000,font-name:'arial',font-size:20,bold:true,italic:true,link:'http://sw2us.com/images/shanghai.png'}, image:{id:1001,width:200,height:200,uri:'http://sw2us.com/images/bear.png'}, audio:{id:2001,duration:5,uri:'http://sw2us.com/clips/a001.mp3'}, location:{lon:121.221,lat,time,speed,direction,text:'立月路2001號(hào)浦星公路口'}, emoticon:{id:201} ], } 屬性名簡(jiǎn)化: --------------------- ----------------------- 1 - text [ 1: text , 2: bg-color , 3: color , 4: font-name, 5:font-size, 6:bold, 7:italic ] 2 - image [ 1: id , 2:width , 3:height , 4:uri] 3 - audio [ 1:id , 2:duration,3:uri] 4 - location [ 1:lon, 2:lat, 3:time, 4:speed, 5:direction, 6:text] 5 - emoticon [ 1: id ] ----------------------- 0 - false 1 - true
2016年9月18日
#
摘要: 項(xiàng)目地址: http://github.com/adoggie/TCE 從12年的時(shí)候開始想做一個(gè)rpc的東東,這些年來陸陸續(xù)續(xù)往里面增加不同的功能、特點(diǎn)。
tce是一個(gè) 全棧的東西,并不是 protocalbuf,或者接近 thrift。 支持語言: csharp,python,java,objc,javascript,actionscript,c++,我想這些夠了。
閱讀全文
2016年8月23日
#
干了17,8年一線技術(shù)工作,還不如剛畢業(yè)的985學(xué)生,真是好笑。
現(xiàn)在覺得也沒啥多想的,現(xiàn)在樂于出去跟不同公司談?wù)劶夹g(shù)問題,面試完,基本也給對(duì)方上完一通技術(shù)課程。
晚上看一17歲小朋友在直播寫帶代碼,滿有意思,自己也想玩玩。
tce工程加入csharp支持中,本地代碼差不多一半,lex分析還沒開動(dòng),要抓緊了,早點(diǎn)能在unity上跑起來。
公司這兩個(gè)月要搞個(gè)證照系統(tǒng),設(shè)計(jì)完框架了,要寫代碼了。
2016年3月24日
#
摘要: 有問題的c++通信代碼的識(shí)別,希望寫c++的碼農(nóng)不要犯同樣的錯(cuò) 閱讀全文
近日獲得一份微信營(yíng)銷系統(tǒng)的代碼,看其功能比較豐富,便開始窺其代碼的實(shí)現(xiàn)。為了將整個(gè)業(yè)務(wù)系統(tǒng)跑起來,還真的花了不少時(shí)間琢磨,幸好不負(fù)我的幾十年功力,終于將運(yùn)營(yíng)環(huán)境和開發(fā)環(huán)境搭建成功,并將系統(tǒng)的授權(quán)代碼全部剔除(軟件廠商控制使用授權(quán))。 準(zhǔn)備條件: 1. 互聯(lián)網(wǎng)服務(wù)器(必須開啟80,443端口) 2. 申請(qǐng)域名,且綁定到服務(wù)器 3. 微信公眾號(hào)申請(qǐng),并通過微信認(rèn)證(300人民幣) 先上系統(tǒng)部署圖 : 環(huán)境配置.jpg) 幾個(gè)部件需要介紹一下: 1. xampp : 開發(fā)php的套件,包含了apache,php,mysql,用起來很簡(jiǎn)單,不過我是部署在linux和mac 上,要留意的是文件目錄訪問權(quán)限的問題,mac下 所有的服務(wù)進(jìn)程跑在root用戶下; 2. phpstrom: 開發(fā)php的ide,出自jetbrains(我個(gè)人理解是目前開發(fā)工具最牛逼的公司)。 管理數(shù)據(jù)庫(kù)推薦 DataGrip 軟件。 3. xdebug : 這個(gè)東西是php與phpstrom的調(diào)試接口 ,apche接收到http請(qǐng)求,轉(zhuǎn)給php解釋器,php解釋器再phpStorm進(jìn)行調(diào)試互動(dòng)(建立xdebug的9000端口的tcp連接),開發(fā)者可以在phpStorm里面隨意下斷點(diǎn)。 注意: 在php.ini中需配置 ide-key:scott , 我是在nginx的轉(zhuǎn)發(fā)頭里面添加了 XDEBUG_SESSION=scott,令所有經(jīng)過 nginx 服務(wù)器的http請(qǐng)求都被轉(zhuǎn)到phpStorm中,否則無法實(shí)現(xiàn)代碼斷點(diǎn)。 4. wxDebuger: 這是微信提供的本地微信頁(yè)面調(diào)試工具,開發(fā)這可以利用winre來調(diào)試手機(jī)上的頁(yè)面,也可以脫離手機(jī),直接調(diào)試微信頁(yè)面(要調(diào)試微信的wxjssdk必須使用wxDebuger)。 5. nginx : 在公網(wǎng)服務(wù)器部署nginx作為http服務(wù)器,接收各種用戶請(qǐng)求,并將其轉(zhuǎn)發(fā)到xampp。 6. vpn : 這個(gè)是關(guān)鍵,為了實(shí)現(xiàn)本地開發(fā)調(diào)試的目的,我在公網(wǎng)服務(wù)器上部署了openvpn,并在mac開發(fā)機(jī)上部署了xampp,phpstorm等,并安裝vpn客戶端 Tunnelblick,其自動(dòng)撥號(hào)到公網(wǎng)服務(wù)器,獲得地址10.8.0.6,nginx將http請(qǐng)求轉(zhuǎn)發(fā)到了我本地的開發(fā)機(jī)器上,這樣我可以很方便的進(jìn)行遠(yuǎn)程和本地調(diào)試了。 主要的功能描述: 1. 手機(jī)、瀏覽器、調(diào)試器 發(fā)起的http請(qǐng)求到達(dá)公網(wǎng)服務(wù)器,nginx通過vpn轉(zhuǎn)發(fā)到本地開發(fā)機(jī),開發(fā)者在phpstorm中斷點(diǎn)調(diào)試代碼,并將處理結(jié)果按原路返回。 2. 微信服務(wù)器的主要作用是獲取 粉絲信息、oauth認(rèn)證回調(diào)、服務(wù)器鑒權(quán)等功能 , HTTP(302)是 oauth的靈魂 。 3. 這種配置架構(gòu)很靈活的可以將開發(fā)模式切換到部署模式,只需要將xampp部署到公網(wǎng)服務(wù)器,并在 nginx的反向代理指到本地xampp服務(wù)即可。 附錄 nginx.conf server { listen 80; server_name wx.xxxx.com www.xxxx.com; proxy_set_header X-real-ip $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / { proxy_pass http://10.8.0.6:8081; proxy_set_header Cookie "$http_cookie;XDEBUG_SESSION=scott"; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-real-ip $remote_addr; } }
2016年1月29日
#
摘要: 6.x 版本系統(tǒng)自帶python 2.6,升級(jí)2.7的方式網(wǎng)上有很多版本,本人試用下來覺得諸多不便。
工作項(xiàng)目中越來越多的開發(fā)特性必須要求工作在py2.7版本中,例如: django 1.7+已經(jīng)不支持 py2.6.x了; pyBox2d也不支持。
這次選擇的最新版本 python 2.7.11 閱讀全文
2015年6月29日
#
訪問sf,記錄下一下代碼 (注冊(cè)sf的app,登記 callback-url,執(zhí)行sql查詢) #coding:utf-8 __author__ = 'scott' import imp imp.load_source('init','../init_script.py') import urllib2,urllib,json,sys,os import traceback,threading,time,struct,os,os.path,shutil,distutils.dir_util,array,base64,zlib,struct,binascii import datetime from libs.python.lemon import webapi callback = 'http://localhost:8002/oauth' client_id = '3MVG9ZL0ppGP5UrC_wQ8U02mOhowPKwjeaaLsWZ3BcYYVqiSsy1rL_D2h6qG.rGPnb_j6IcgLHPdhmvomzDFj' client_secret = '9046731979xxxxxxx'
def accessToken(request,code,state): url = 'https://login.salesforce.com/services/oauth2/token' data = { 'grant_type':'authorization_code', 'code':code, 'client_id':client_id, 'client_secret':client_secret, 'redirect_uri':callback } result = '' try: result = urllib2.urlopen(url,urllib.urlencode(data) ) except: traceback.print_exc() result = result.read() return json.loads( result )
def oauth(request): cr = webapi.SuccCallReturn() code = webapi.GET(request,'code','') state = webapi.GET(request,'state','') cr.result=[code,state] token = accessToken(request,code,state) cr.result.append(token) print token try: sqlExecute(token['access_token'],token['instance_url']) except: traceback.print_exc() return cr.httpResponse()
import cookielib
# -H "Authorization: OAuth token" -H "X-PrettyPrint:1" " def sqlExecute(token,url_host): httpHandler = urllib2.HTTPHandler(debuglevel=1) httpsHandler = urllib2.HTTPSHandler(debuglevel=1) opener = urllib2.build_opener(httpHandler, httpsHandler) urllib2.install_opener(opener) sf_cmd_query="%s/services/data/v20.0/query/?%s"%(url_host, urllib.urlencode({'q':'select count() from account'})) headers = { 'Authorization':'OAuth %s'%token, 'X-PrettyPrint':1 } httpReq = urllib2.Request( sf_cmd_query,headers=headers ) r = opener.open(httpReq).read() print r pass
url1 = """https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id=%s&redirect_uri=%s&state=first"""%(client_id,callback)
def launchBrowserForOAuth(): import webbrowser webbrowser.open(url1)
if __name__ == '__main__': launchBrowserForOAuth()
2015年5月26日
#
python內(nèi)部數(shù)據(jù)容器有dict和list兩種 ,工作中最常用的方式是定義一些數(shù)據(jù)結(jié)構(gòu)(數(shù)據(jù)即代碼),例如:
1 frog={'name':'scott', 2 'age':2, 3 'parts':{ 4 'eye':'green','leg':85 5 }, 6 ''friend":['moee','wee'], 7 "hometown":'affica' 8 } frog對(duì)象定義了小動(dòng)物的某些屬性,訪問frog對(duì)象屬性時(shí),通過 dict,list的取值方法進(jìn)行訪問,例如: print frog['name'] print frog['friend'][0] 有時(shí)覺得這種表達(dá)方式太原始了,需要改進(jìn),最好是以 '.'方式訪問對(duì)象屬性,例如: print frog.name 代碼來開始和結(jié)束吧, class _x 1 class _x: 2 """ 3 從簡(jiǎn)單數(shù)據(jù)類型轉(zhuǎn)換成python對(duì)象 4 5 p = _x({'name':'boob','body':{'color':'black'},'toys':[1,2,3,],'age':100}) 6 print p['toys'][1] 7 print len(p.toys) 8 print p.body.colors 9 """ 10 def __init__(self,primitive): 11 self.data = primitive 12 13 def __getattr__(self, item): 14 value = self.data.get(item,None) 15 if type(value) == dict: 16 value = _x(value) 17 return value 18 19 def __len__(self): 20 return len(self.data) 21 22 def __str__(self): 23 return str(self.data) 24 25 def __getitem__(self, item): 26 value = None 27 if type(self.data) in (list,tuple): 28 value = self.data[item] 29 if type(value) in (dict,list,tuple): 30 value = _x(value) 31 elif type(self.data) == dict: 32 value = self.__getattr__(item) 33 return value
2015年1月1日
#
相關(guān)技術(shù): haproxy_keepalived_nginx_uwsgi_gevent_django
之前部署django一直采用 apache + mod_wsgi,用得倒也沒啥問題,看到越來越多的人采用nginx部署,所以也嘗試了一下,結(jié)果很讓人欣喜。
nginx夠小夠簡(jiǎn)潔,編譯、配置相當(dāng)簡(jiǎn)單,但要知道她僅僅是個(gè)靜態(tài)webserver,動(dòng)態(tài)功能需要搭配相應(yīng)的cgi來實(shí)現(xiàn); uwsgi是個(gè)啥東西,看其官方文檔還真寫的相當(dāng)詳細(xì),功能很豐富,但我的需求可能只會(huì)使用其30%的功能; uwsgi可以認(rèn)為是python代碼運(yùn)行的loader,或者是容器(container),這有點(diǎn)像java的container(resin,tomcat)。看了其配置文檔,很是驚喜,其不僅可以配置為多進(jìn)程+多線程模式,也可以配置為單進(jìn)程+多線程模式,并能保持高并發(fā)高銷率,非常感興趣。 一直以來自己總在尋找一種 高效、靈活的django的應(yīng)用容器。 apache默認(rèn)都是多進(jìn)程模式,http又是無狀態(tài)的,不同的請(qǐng)求被分派到不同的進(jìn)程處理,request處理都是隔離的。多進(jìn)程帶來的問題是高昂的系統(tǒng)開銷(apache也支持多線程處理)。 這種隔離又帶來了諸多不便,request之間不能共享狀態(tài)、數(shù)據(jù)和協(xié)作,不能很好的完成與外部系統(tǒng)的協(xié)同工作(例如request共享同一個(gè)服務(wù)器的socket連接或者訪問控制某個(gè)rs232端口) 所以很想有種類似java的應(yīng)用容器這樣的東東。 接觸了gevent,其核心是io異步分派,單線程模擬多協(xié)程來對(duì)應(yīng)用層多任務(wù)的支持,幾近瘋狂io效率得到了我的認(rèn)可。ps:八過smp系統(tǒng)就應(yīng)該啟動(dòng)多個(gè)gevent服務(wù),不然其他核心數(shù)都浪費(fèi)了。 采用gevent+django的模式搭建了自己得app容器,也跑了幾個(gè)項(xiàng)目,總體效果還是可以。 nginx+uwsgi+django 的配合開始應(yīng)用到新項(xiàng)目中
2014年10月8日
#
上海交通違章查詢網(wǎng)站: http://www.shjtaq.com/Server1/dzjc_new.asp 驗(yàn)證碼圖片獲取地址: http://www.shjtaq.com/Server1/validatecode.asp?m=2304.046
服務(wù)器通過頁(yè)面請(qǐng)求的session-id來區(qū)分之后提交的驗(yàn)證碼。 第一次請(qǐng)求查詢頁(yè)面時(shí),服務(wù)器將訪問session(cookie)傳到客戶端,之后的查詢和驗(yàn)證碼獲取時(shí)客戶端攜帶之前的cookie傳送到服務(wù)器,服務(wù)器端保存著當(dāng)前 session-id與驗(yàn)證碼 的對(duì)應(yīng)關(guān)系。
查詢返回記錄可通過 xpath或者 beautifulsoup進(jìn)行解析
程序使用python完成,也是個(gè)簡(jiǎn)單的小爬蟲,scrapy 之類的沒必要使用了,gevent完成異步通信。
交通網(wǎng)的驗(yàn)證碼生成還是比較簡(jiǎn)單,做自動(dòng)識(shí)別可找?guī)讉€(gè)簡(jiǎn)單的圖形識(shí)別程序即可。 如若不行,則人工輸入嘍
2014年5月20日
#
|