用Python写一个本地Sogou代理服务器程序

真难以自信,使用Python强大的类库,可以用这么简短的代码就写好一个本地的HTTP代理!
真难以自信,这是我用Python花了连续6个小时写的第一个程序(之前写的一个Hello world除外)!
真难以自信,我就这样爱上了Python……
所以,以后在我博客上估计会有不少Python代码了……

现在我使用Python仍然停留在Thinking In The C++ Way而不是Thinking In The Python Way,所以最近会打算看一些Python类库里面的代码,看看别人是如何写的。

一开始使用Python3.2编写这个代理服务器,后来移植到Python2.7上去,这两个版本的差异还真的挺大的,我记得移植的时候改了不少地方。
我用py2exe编译了不需要Python运行环境的Windows可执行文件版本,方便大家测试,貌似编译之后比较臃肿。

这里有一篇关于如何使用py2exe编译python脚本的文章:
www.cnblogs.com/jans2002/archive/2006/09/30/519393.html

下载地址:sogouproxy win32

Python源代码:

  1. ''''' 
  2.     Hey guys! 
  3.     This is a the first python program(except hello worlds) I have written.  
  4.     With HTTPServer, I can easily write a webserver. 
  5.     Python is such a powerful language that many complicated problems can be 
  6.     solved by a few lines of code. 
  7.  
  8.     Welcome to visit my blog: www.xiaoxia.org 
  9.     The proxy program is just coded for fun :-) 
  10. '''  
  11.   
  12. from threading import Thread  
  13. from struct import unpack  
  14. from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer  
  15. from httplib import HTTPResponse  
  16. from SocketServer import ThreadingMixIn  
  17. import socket  
  18. import time, sys, random  
  19.   
  20. x_sogou_auth = "9CD285F1E7ADB0BD403C22AD1D545F40/30/853edc6d49ba4e27"  
  21. proxy_host = "h0.cnc.bj.ie.sogou.com"  
  22. proxy_port = 80  
  23.   
  24. def calc_sogou_hash(t, host):  
  25.     s = (t + host + 'SogouExplorerProxy').encode('ascii')  
  26.     code = len(s)  
  27.     dwords = int(len(s)/4)  
  28.     rest = len(s) % 4  
  29.     v = unpack(str(dwords) + 'i'+str(rest)+'s', s)  
  30.     for vv in v:  
  31.         if(type(vv)==type('i')):  
  32.             break  
  33.         a = (vv & 0xFFFF)  
  34.         b = (vv >> 16)  
  35.         code += a  
  36.         code = code ^ (((code<<5)^b) << 0xb)  
  37.         # To avoid overflows  
  38.         code &= 0xffffffff  
  39.         code += code >> 0xb  
  40.     if rest == 3:  
  41.         code += ord(s[len(s)-2]) * 256 + ord(s[len(s)-3])  
  42.         code = code ^ ((code ^ (ord(s[len(s)-1])*4)) << 0x10)  
  43.         code &= 0xffffffff  
  44.         code += code >> 0xb  
  45.     elif rest == 2:  
  46.         code += ord(s[len(s)-1]) * 256 + ord(s[len(s)-2])  
  47.         code ^= code << 0xb  
  48.         code &= 0xffffffff  
  49.         code += code >> 0x11  
  50.     elif rest == 1:  
  51.         code += ord(s[len(s)-1])  
  52.         code ^= code << 0xa  
  53.         code &= 0xffffffff  
  54.         code += code >> 0x1  
  55.     code ^= code * 8  
  56.     code &= 0xffffffff  
  57.     code += code >> 5  
  58.     code ^= code << 4  
  59.     code = code & 0xffffffff  
  60.     code += code >> 0x11  
  61.     code ^= code << 0x19  
  62.     code = code & 0xffffffff  
  63.     code += code >> 6  
  64.     code = code & 0xffffffff  
  65.     return hex(code)[2:].rstrip('L').zfill(8)  
  66.   
  67. class Handler(BaseHTTPRequestHandler):  
  68.     s = 0  
  69.     def do_proxy(self):  
  70.         try:  
  71.             if self.s == 0:  
  72.                 self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
  73.                 self.s.connect((proxy_host, proxy_port))  
  74.             self.s.send(self.requestline.encode('ascii') + b"\r\n")  
  75.             # Add Sogou Verification Tags  
  76.             self.headers["X-Sogou-Auth"] = x_sogou_auth  
  77.             t = hex(int(time.time()))[2:].rstrip('L').zfill(8)  
  78.             self.headers["X-Sogou-Tag"] = calc_sogou_hash(t, self.headers['Host'])  
  79.             self.headers["X-Sogou-Timestamp"] = t  
  80.             self.s.send(str(self.headers).encode('ascii') + b"\r\n")  
  81.             # Send Post data  
  82.             if(self.command=='POST'):  
  83.                 self.s.send(self.rfile.read(int(self.headers['Content-Length'])))  
  84.             response = HTTPResponse(self.s, method=self.command, buffering=True)  
  85.             response.begin()  
  86.             # Reply to the browser  
  87.             status = "HTTP/1.1 " + str(response.status) + " " + response.reason  
  88.             self.wfile.write(status.encode('ascii') + b'\r\n')  
  89.             h = ''  
  90.             for hh, vv in response.getheaders():  
  91.                 if hh.upper()!='TRANSFER-ENCODING':  
  92.                     h += hh + ': ' + vv + '\r\n'  
  93.             self.wfile.write(h.encode('ascii') + b'\r\n')  
  94.             while True:  
  95.                 response_data = response.read(8192)  
  96.                 if(len(response_data) == 0):  
  97.                     break  
  98.                 self.wfile.write(response_data)  
  99.         except socket.error:  
  100.             print('socket error for ' + self.requestline)  
  101.     def do_POST(self):  
  102.         self.do_proxy()  
  103.     def do_GET(self):  
  104.         self.do_proxy()  
  105.   
  106. class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):  
  107.     pass  
  108.   
  109. server = ThreadingHTTPServer(("127.0.0.1"1998), Handler)  
  110.   
  111. #print(calc_sogou_hash('4d8cdaed', 'www.youku.com'))  
  112.   
  113. print('Please select your network:\n\  
  114.       1. CERNET(The China Education and Research Network)\n\  
  115.       2. CTCNET(China Telecommunications Corporation)\n\  
  116.       3. CNCNET(China NetCom)\n\  
  117.       4. DXT(Dian Xin Tong)\n')  
  118. i = int(input('Input the number: '))  
  119. if i==1:  
  120.     proxy_host = 'h' + str(random.randint(0,10)) + '.edu.bj.ie.sogou.com'  
  121. elif i==2:  
  122.     proxy_host = 'h' + str(random.randint(0,3)) + '.ctc.bj.ie.sogou.com'  
  123. elif i==3:  
  124.     proxy_host = 'h' + str(random.randint(0,3)) + '.cnc.bj.ie.sogou.com'  
  125. elif i==4:  
  126.     proxy_host = 'h' + str(random.randint(0,10)) + '.dxt.bj.ie.sogou.com'  
  127.   
  128. print('Proxy over ' + proxy_host)  
  129. server.serve_forever()  

用Python写一个本地Sogou代理服务器程序》有39个想法

  1. whitefirer

    又多了个pythoner~~……像你原来提到过的notify用python的话就几行

    另,我觉得最后那段写到main里会好些

    回复
    1. Xiaoxia 文章作者

      官方有库的手册,网上也有很多实例代码,用起来还是挺方便的。
      而且,我也经常去翻库函数的代码看,看一下它的代码实现就更好了。
      Python的标准库的代码阅读起来很爽,比起C++的STL代码,更好看,更易懂啊!

      回复
            1. Xiaoxia 文章作者

              好像就是IE core的浏览器看不了Python的代码!!!
              哈哈,要看代码,大家都用Firefox或者Chrome吧……

              回复
  2. Mike Ma

    表示fedora的yum就是用python写的……
    个人虽然喜欢python,但是还是喜欢c/vala 更多吧(对解释型无爱)
    写代理服务器应该性能要求更大吧

    回复
    1. Xiaoxia 文章作者

      对,如果要做出产品给用户使用的话,为了满足性能上的需求,还是C/C++比较实际。
      Python方便我写测试代码。

      回复
  3. r2ddrr2

    楼主,你的软件编的真的很好啊。有一个问题,为什么用了你的代理后,打不开qq邮箱之类的?

    回复
  4. 真难以置信,我想在linux下不用wine使用sogou代理的多年夙愿就这样实现了!
    真难以置信,还是用我最爱的python写的!
    真难以置信,楼主还是hello world之后就写了这个!!!
    …果断订阅小虾的rss!!

    泪流满面,妈妈再也不用担心我在教育网下用linux和mac os x上不了各种网站了…谢谢谢谢楼主!!!

    回复
        1. Xiaoxia 文章作者

          你怎么运行的呀?
          例如保存为proxy.py。
          在终端里,输入
          root@xiaoxia-pc:~# python proxy.py 回车。

          显示如下:
          root@xiaoxia-pc:~# python proxy.py
          Please select your network:
          1. CERNET(The China Education and Research Network)
          2. CTCNET(China Telecommunications Corporation)
          3. CNCNET(China NetCom)
          4. DXT(Dian Xin Tong)

          Input the number: 1
          Proxy over h3.edu.bj.ie.sogou.com

          回复
  5. Pingback引用通告: Python写简单的网络服务器示例 « Xiaoxia[PG]

  6. Pingback引用通告: Linux下独立使用搜狗浏览器代理 | Ernest's Blog

    1. Xiaoxia 文章作者

      登录用到了https了吧!!!我周一或周二发一个完美支持https的sogou代理版本,关注我的文章哈哈。

      回复
  7. Pingback引用通告: 用Python写的本地Sogou代理服务器程序 | 核桃薄壳

回复 Xiaoxia 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据