分类存档: Python

python模拟飞信(模拟webim)

之前写过一点飞信相关的小程序。很久没关心了。发现现在飞信协议都改掉了。强制了验证码。基本上原来的第三方库都不能使用了。

下面就是现在的飞信验证码。看上去破解难度不大。就一根干扰线。有哪位可以破解的网友贡献下代码to me<me[???]fengsage.com> 替换[???]你懂得。
飞信验证码

废话不多说,开始进入正文。

最近发现飞信官网出了webim版的飞信。而且因为年底工作不多。有点无聊。花了几周无聊时间写写代码。给自己发发短信神马的。没多大意义。

项目地址:http://code.google.com/p/fetionim/

值得注意的地方:

  1. 这个程序不是api库。如果验证码能破解则可以作为API库。
  2. 这个程序需要不关机环境。因为要保持和飞信server的心跳连接。一旦关机需要重新登录。
  3. 很多未知bug

目前实现的功能:

  1. 简单的cron表达式。目前只支持 month day hour minute 四个区间. 支持一个*通配符。一般用用够了。举例:[* * * *]表示每分钟执行到。[* * 20 00]表示每天20点执行。[* 20 * *] 表示每月20日的每一分钟执行到。[12 20 20 1]表示12月20日20点1分执行到。
  2. 只支持2种定时任务。即天气预报(只支持嘉兴.因为我住这)和任意短信。

未来要实现的功能:

  1. 天气预报各地支持。这块实现起来很简单。但打算重新设计下任务模块和cron模块。到时候一起改。
  2. 开放一些api。方便其他程序连接。比如宏机短信……
  3. 做个wordpress插件。方便博友直接通过短信联系作者。

 一些废话:

本来不打算发布这个。个人感觉这玩意不能算是什么好的作品。不过以我个性,如果不发布这玩意。估计后面也懒得去维护了。索性发布。代码写的不好。看到的朋友请口水少喷。多提点实在点的意见。

java和ruby都有基于webim的类似实现。

java参见:litefetion
ruby参见:fetion-robot

python的应该算是独一无二的。我没看过这些现有的代码是如何实现的。纯粹自己编写边想。思路和方式和他们应该都存在较多的不同。算是给python初学者提供一些例子吧。

 

wordpress图片搬家脚本

历经几次换域名,以及从GAE-wordpress造成不少历史遗留的图片分布在不同域名或gae目录下。

主要分布
http://oldres.fengsage.com
http://www.fengsage.com
http://fensageblog.appspot.com

原来使用代码实现图片代理访问。但自己越看越不爽。索性写个脚本一次性把原来的图片下载到wordpress本地。并且更新数据库。主要是圣诞节闲的蛋疼。

代码有不少问题:

  1. 不用php,因为懒得看wordpress插件制作。
  2. 因为是python脚本,所以必须是有执行python的权限
  3. 没有生成wordpress media记录。不能后台编辑多媒体

wordpress插件实现:

http://wordpress.org/extend/plugins/velvet-blues-update-urls/  等发现的时候脚本已经写好了。悲哀~~

脚本笔记简单。分享下。

#!/usr/bin/env python
# --*-- encoding:utf-8 --*--
'''
Created on 2011-12-25
@author: fred 
'''

import MySQLdb
import re
import urllib
import time
import os

WP_POST_CONTENT = u"wp_posts"
SIMPLE_IMG_URL = r'' 
NEW_IMG_URL = u''
DOWNLOAD_PATH = u'wp-content/uploads/%s'%(time.strftime('%m/%d', time.localtime(time.time())))

REPLACE_LIST = ['http://oldres.fengsage.com','../media','http://www.fengsage.com']

conn = MySQLdb.connect(host="localhost",
                         user="root",
                         passwd="zhufeng",
                         db="wordpress",
                         charset='utf8')


def get_post_list():
    cursor = conn.cursor()
    cursor.execute("SET NAMES utf8")
    cursor.execute("select * from %s"%WP_POST_CONTENT);
    return cursor.fetchall()

def find_img_urls(str):
    pattern = re.compile(SIMPLE_IMG_URL) 
    match = pattern.findall(str)
    if match:
        return match
    return None

def process_imgs(img_urls,replace):
    result = {}
    for img in img_urls:
        for rp in replace:
            if img.find(rp)>=0:
                print "\tdownload picture"
                new_img_ath = download_img(img)
                result.update({img:new_img_ath})
    return result
                
def download_img(img_url):
    IMG_NAME_REG = r'([^./]*).(png|jpg|gif|jpeg|bmp)'
    m = re.findall(IMG_NAME_REG, img_url)
    if m:
        name,suf = m[0]
        if os.path.isdir(DOWNLOAD_PATH) == False:
            os.makedirs(DOWNLOAD_PATH)
        file_path = u'%s/%s.%s'%(DOWNLOAD_PATH,name,suf)
        downloaded_image = file(file_path.encode('utf-8'), "wb")
        try:
            image_on_web = urllib.urlopen(img_url.encode('utf-8'))
            while True:
                buf = image_on_web.read(65536)
                if len(buf) == 0:
                    break
                downloaded_image.write(buf)
            downloaded_image.close()
            image_on_web.close()
            return file_path
        except:
            print '\tdownload img failture:%s'%img_url

def refresh_content(post_content,result):
    for k in result.keys():
        post_content = post_content.replace(k,'%s/%s'%(NEW_IMG_URL,result[k]))
    return post_content

def update_content(post_id,post_content):
    sql = "update "+WP_POST_CONTENT+" set post_content=%s where ID=%s"
    cursor = conn.cursor()
    cursor.execute("SET NAMES utf8")
    cursor.execute(sql,(post_content,post_id))
    
    
def go():
    post_list = get_post_list()
    for post in post_list:
        post_id = post[0]
        post_content = post[4]
        post_title = post[5]
        if post_id and post_content and post_title:
            print "process article ID:%s"%(post_id)
            img_urls = find_img_urls(post_content)
            if img_urls:
                result = process_imgs(img_urls,REPLACE_LIST)
                if result and len(result)>0:
                    post_content = refresh_content(post_content,result)
                    try:
                        update_content(post_id,post_content)
                    except Exception, e:
                        print 'update database failture:%s'%e
                        

if __name__ == '__main__': 
    print go()

一段自动登录淘宝接口Python代码

新公司这边客服流动频繁,为防止密码泄露,写了个小脚本.可以让用户在不知道密码的情况下自动登录淘宝

主要代码:

#!/usr/bin/python2.5

# -*- coding: utf-8 -*-

'''

Created on 2011-5-28

@author: fred <me@fengsage.com>

'''

'''

自动登录淘宝脚本

'''

def login_taobao(username, password):

  from apps.PAM30 import PAMIE

  ie = PAMIE()

  ie.navigate("https://login.taobao.com/member/login.jhtml")

  tmp_element = ie.findElement('input','name','loginType')

  if tmp_element.getAttribute("value")=="4":

    checkBox = ie.findElement('input', 'id', 'J_SafeLoginCheck')

    ie.clickElement(checkBox)

  if ie.textBoxExists('TPL_username') and ie.textBoxExists('TPL_password'):

    ie.setTextBox('TPL_username', username)

    ie.setTextBox('TPL_password', password)

    loginbtn = ie.findElement('button', 'type', 'submit')

    ie.clickElement(loginbtn)

使用PAMIE,可以轻松控制IE做任何操作~~

I love Python~

一段linux启动脚本(python版)

公司项目用到需要开机自动执行相关程序,奈何shell不是很精通,老大给了段python版的,我也分享下,供大家参考

#!/usr/bin/env python

# init.d script for the Mytut CS Repo Server; John Wang 14 Feb 2011

import sys,subprocess,time

cmmd    = '/home/fred/test.py'#启动/关闭执行命令

port    = '12600'

decp    = 'start process program....'

cmmdln  = ['nohup',cmmd,'-p',port]

def start():

print 'Starting %s...' % decp

subprocess.Popen(cmmdln)

print 'Started'

def stop():

print 'Stopping %s...' % decp

subprocess.Popen(cmmdln)

print 'Stopped'

return 0

def restart():

if stop()==1:

print 'Stopping error. Maybe already stopped ?. starting anyway ...'

else:

time.sleep(1)

start()

def run(argv):

fns={

    'start':start,

    'stop':stop,

    'restart':restart,

    'reload':restart,

}

fn=fns.get(argv[1],None) if len(argv)>1 else None

if not fn:

print >> sys.stderr,"Usage: %s {%s}" % (argv[0],'|'.join(fns.keys()))

sys.exit()

fn()

if __name__ == '__main__':

run(sys.argv)

比较简单~

前文介绍过,放在/etc/rc3.d 目录下即可,linux启动后会自动执行这个目录里面的脚本,默认使用start参数启动

博客重构完毕(Reconstruct Blog)

花了2个月时间,终于把博客从micolog完全转到自己的构架上来

 

放弃micolog的原因很多,但不可否认micolog是一款在GAE上出色的Blog.但也因为GAE因为GWF作怪,活跃度不是很高.导致micolog的发展一直不是很快

考虑到micolog自身因设计时候造成代码的冗余以及体积的庞大,自己就重造了一会轮子. ╮(╯▽╰)╭ 上天原谅我吧.

博客重构后,重点考虑到了性能问题,因此在次方面进行了优化,网速正常情况下

访问http://i-studio.appspot.com只需要2s

访问http://www.fengsage.com 由于反向代理的关系,一般在5s-10s内打开

http://fengsageblog.appspot.com 访问都会自动跳转到相应的http://i-studio.appspot.com页面上来

目前运行已经一周,尚运行稳定.

 

————————Exercise English—————————–

Take me two months, I reconstruct my blog on GoogleAppEngine.

Micolog is very good blog on GoogleAppEngine. everyone can download the srouce from http://code.google.com/p/micolog/

But i also have some reason give up it.

1. The blog develop very slow. the author long time update. i think the GWF is important reason that it also closed the connection when chinese person visted GAE.

2. The blog code not beautiful. ok, because author using python.  me too. i like the code more simple and beautifule.

╮(╯▽╰)╭

I take long time optimizing the connection spped when chinese person visited it.

if visted http://i-studio.appspot.com only need 2s

if vised http://www.fengsage.com may be need 5-10s

older person can connection the old url. all request will auto skip the new url http://i-studio.appspot.com

 

以后有机会,写博文都加一篇英文的~  练习练习鸟语~

 

使用Google Captcha作网站的验证码(Python)

CAPTCHA 是Completely Automated Public Turing test to tell Computers and Humans Apart的缩写,够长吧!中文意思是:"全自动区分电脑与人类的图灵测试" 简单来说就是用于区分人类和电脑的验证码图片.

感谢伟大的Google提供了其实现和相应的API. 相关文档大家可自行参考:

http://www.google.com/recaptcha

最近公司的一个项目要使用验证码防止恶意脚本批量注册或遍历破解密码. 传统的解决方式很多,比如IP记录,验证码…但最常见的还是验证码功能,但现在验证码也是有很多弱点的,很容易被破解. 敢兴趣的朋友可以参看相关文章(http://www.xklog.org/article/internet/python-verify-code-recognize-discuz.html) 其实最主要想使用Google Captacha的原因是想省力气,懒得写太复杂的算法.  囧~呵呵

Google Captacha有相应的python实现,但是我感觉默认库可定制性太差,所以只部分采用.

开始之前我先来说下Google Captacha的原理.

传统的验证码是网站先随即生成一个字符,然后保存字符串到session或数据库中.然后把这个字符串生成图片,输出到页面上去.

Google Captacha构架如下图:

 

步骤看上去比较多,其实对网站开发者来说重点是3步.即图上的1、3、4. 下面稍微解释下

第一步是用户从Google服务器上得到一个验证码图片

没错,是用户获取。对开发人员来说就是在页面加一个ajax调用,当用户加载页面的同时,加载一个Google Capatcha图片即可.

第二步是当用户把含验证码信息表单提到后台,也是web应用最常见的步骤.

第三步是网站后台把用户得到的验证码传递给Google Capatcha服务器验证用户输入的是否正确.

这里就是重点所在,Google服务器如何知道当前验证码输入是否和第一步用户请求到的图片一致,就需要一样东西,即一个随机码. 此外要确定是哪一个网站用户申请的图片和哪一个网站验证图片,需要另外一样东西,即私钥/公钥.

上面简单介绍了下原理,对开发人员来说读代码比看文章管用的多.下面直接开始

一、注册网站私/公钥.https://www.google.com/recaptcha/admin/create

Public Key:

6LcmCL8S*****JH2rJ5l9mgj9xIq63wM0Qeliafm

Private Key:

6LcmCL8S******DFxZh7GY-nWdklo9zWJpQ9Y0yY4

二、编写用户页面,公钥是用户向Google服务器请求一个Capatcha图片. 此步骤需要用户公钥

由于国内加载GoogleCapatcha图片比较慢,我用了异步请求.大致代码如下

HTML


				

写个百度搬家玩玩

今天下午实在无聊. 好几天都没事做~ 整天就收发邮件,都快成文秘了. 大笑

随便写了百度搬家工具打发下时间,这是从原来的python百度搬家工具改的. 希望越来越多的朋友”背叛”baidu.加入micolog阵营!

django邮件发送(支持模板)

项目里一个模块,重新封装了python的smtplib和django的template

主要功能:

  1. 支持多用户接受

  2. 支持模板

  3. 良好的处理了中文问题

代码如下:


				#!/usr/bin/env python

				# -*- coding: UTF-8 -*-

				#

				#

				__author__="Fred"

				__date__ ="$2010-5-31 17:15:35$"

				import smtplib, base64

				from django.template import loader, Context

				CHARSET = 'utf-8'

				FROM_ADD = 'xxxxxx@163.com'

				SMTP_SERVER = 'smtp.163.com'

				SMTP_USER = 'xxxxx'

				SMTP_PASS = 'xxxxx'

				class SendMail:

				u'''

				邮件发送模块,此模块运行使用django模块来发送邮件

				参数介绍(*必填):

				subject *邮件主题

				template *邮件模板位置

				context *邮件模板上下文

				to_addr *目的地址,允许发给多人,格式为['test@examp.com','test2@example',......]

				smtp_server 发件服务器地址

				smtp_server_port 发件服务器端口号

				from_addr 发信地址

				from_addr_name 发信人名称

				user 发件箱登录用户名

				pass 发件箱登录密码

				e.g:

				from ureg.helper import SendMail

				mail = SendMail('test','email/register.html',{'tmp_code':'123'},['ad@fengsage.cn'])

				mail.send_mail()

				u'''

				def __init__(self,subject,template,context,to_addr,smtp_server=SMTP_SERVER, smtp_server_port = 25 ,from_addr=FROM_ADD,from_addr_name=u'Mytut视频网',user=SMTP_USER, passwd=SMTP_PASS):

				self.subject = subject

				self.template = template

				self.context = context

				self.to_addr  = to_addr

				self.from_addr = from_addr

				self.from_addr_name = from_addr_name

				self.username = user

				self.password = passwd

				self.smtp_server_port = smtp_server_port

				self.mailserver = smtp_server

				def send_mail(self):

				from email.mime.text import MIMEText

				from email.mime.multipart import MIMEMultipart

				from email import Utils

				msgRoot = MIMEMultipart('related')

				msgRoot['Subject'] = self.subject

				msgRoot['From'] =  self.named(self.from_addr, self.from_addr_name)

				if len(self.to_addr) == 1:

				msgRoot['To'] = self.to_addr[0]

				else:

				msgRoot['To'] = Utils.COMMASPACE.join(self.to_addr)

				pass

				msgRoot['Date'] = Utils.formatdate()

				# Encapsulate the plain and HTML versions of the message body in an

				# 'alternative' part, so message agents can decide which they want to display.

				msgAlternative = MIMEMultipart('alternative')

				msgRoot.attach(msgAlternative)

				#根据模板生成html

				html = self.render(self.template, self.context).encode('utf-8')

				msgText = MIMEText(html,'html',_charset='utf-8')

				msgAlternative.attach(msgText)

				smtp = smtplib.SMTP(self.mailserver,self.smtp_server_port)

				smtp.login(self.username, self.password)

				result = smtp.sendmail(self.from_addr, self.to_addr, msgRoot.as_string())

				smtp.quit()

				def render(self,template,context):

				u'''

				读取模板内容,并赋值

				u'''

				if template:

				t = loader.get_template(template)

				return t.render(Context(context))

				return context

				def named(self,mail,name):

				u'''

				格式化右键发信/收信格式

				e.g fredzhu <me@fengsage.cn>

				u'''

				if name:

				return '%s <%s>' % (name,mail)

				return mail

				

使用方法:


				mail = SendMail(USER_REGISTER,'email/register.html',{'tmp_code':tmp_code,'tmp_user':username},[email])

				mail.send_mail()

 

micolog自动slug(修正)

核心代码

def autoSlug(str):
    translate_url = ‘http://translate.google.com/translate_a/t?client=t&text=%s&hl=en&sl=zh-CN&tl=en&pc=0′%str.replace(‘ ‘,‘-‘).encode(“utf-8”)
    translate_result = urlfetch.fetch(translate_url,None,urlfetch.GET,HEADERS)
   
    if translate_result.status_code == 200:
        trans_reg = u'”trans”:”([^”]*)”‘
        translate_content = re.findall(trans_reg, translate_result.content)[0]

        translate_content = translate_content  
                        .replace(‘ ‘,‘-‘)  
                        .replace(\,‘-‘)

        translate_content = re.sub(u'[^a-zA-Zd_]’,‘-‘, translate_content)

        logging.info(“*********”+translate_content)
        return translate_content

效果可以看我每篇文章的url,懒人必备,呵呵

补充. 上述代码需插入admin.py,并修改admin_entry类的entry.slug=entry_slug.replace(” “,”-“)为entry.slug=autoSlug(title) 即可。 但这样做会增加提交文章时额外的时间. 在GAE找个不稳定的环境下,及容易崩溃.因此可以用下面方法代替上述方法.

  1. 找到micolog/views/admin/entry.html页面.
  2. 找到大概288行,有段<input type=”text” value=”{{entry.slug|escape}}” tabindex=”1″ size=”30″ name=”slug”/></br>.在</br>换行标记前插入<input id=”auto_translate” type=”button” value=”auto”>标签.
  3. 然后回滚到该页面最上面,随便找一行空白,加入下面代码
JavaScript语言: 临时自用代码
<script type=“text/javascript” src=“http://www.google.com/jsapi”></script>
<script type=“text/javascript”>
    google.load(“language”, “1”);
    $(function(){
        $(‘#auto_translate’).click(function(){
            var title = $(“#title”).val();
            if(title!=“”){
                google.language.translate(title,“zh-CN”,“en”,function(result) {
                    res = result.translation.replace(/s{1,}/g,‘-‘);
                    $(“input[name=’slug’][type=’text’]”).val(res);
                  });

            }else{
                alert(‘请先输入标题!’);
            }
        });
    });
</script>

最终效果如图,

Python百度搬家工具v0.1

目的
转移百度空间内所有博文

原理
1、分析空间页数
2、遍历每一页文章url
3、对每个url进行分析、采集数据
4、输出固定格式,目前只支持输入RSS2.0

项目地址  http://fengtoys.googlecode.com/svn/trunk/BaiduMove/

使用方法

编辑BaiduMove.py文件,找到if __name__==’__main__’:行,修改下一行的baidu==BaiduMove(‘fred’,’429263181′)429263181替换成自己的博客ID

if __name__=='__main__':
				baidu = BaiduMove('fred','429263181')
				baidu.articleToRSS('Hibaidu_fred',10)

然后在命令行运行python BaiduMove.py即可

由于是要采集到一个文件里,因此暂不支持多线程,难实现不同线程操作对一个文件写入,有什么好主意可以进一步讨论

v0.1
1、自动爬百度空间,并输出RSS文件

v0.2
1、修复部分bug
2、支持RSS切割生成