标签存档: 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数字分页工具

有点造轮子的嫌疑,感觉Django自带的分页工具不是很好用,部分重写了下

Python代码

class Pagination():
				'''
				Pagination tools
				'''
				count = 0
				page_size = 10
				current_page = 1
				page_gap = 5
				page_count = 0

				def __init__(self,object_list,page_size,current_page = 1,page_gap=5):
				u'''Simple Pagination tools
				object_list: The queue or list objects
				page_size:    Page size
				current_page: Current Page
				page_gap:    The gap of current page, inlcude left gap and right gap. the same value is this.
				'''
				self.object_list = object_list
				self.count = self._get_count()
				self.page_size = page_size
				self.current_page = current_page
				self.page_gap = page_gap
				if not self.count % page_size:
				self.page_count = self.count / page_size
				else:
				self.page_count = self.count / page_size + 1

				def _get_count(self):
				"Returns the total number of objects, across all pages."
				try:
				self.count = self.object_list.count()
				except (AttributeError, TypeError):
				self.count = len(self.object_list)
				return self.count

				def page_objects(self):
				bottom = (self.current_page-1)*self.page_size
				top = bottom + self.page_size
				if top >= self.count:
				top = self.count
				return self.object_list[bottom:top]

				def has_pre(self):
				if self.current_page > 1:
				return True
				return False

				def has_next(self):
				if self.current_page < self.page_count:
				return True
				return False

				def has_first(self):
				if self.current_page == 1:
				return False
				return True

				def has_last(self):
				if self.current_page == self.page_count:
				return False
				return True

				def page_limit(self):
				return self.page_size * (self.current_page - 1)

				def page_left_list(self):
				if self.current_page > self.page_gap:
				return range(self.page_count+1)[self.current_page-self.page_gap:self.current_page]
				return range(self.page_count+1)[1:self.current_page]

				def page_right_list(self):
				if self.current_page + self.page_gap <= self.page_count:
				return range(self.page_count+1)[self.current_page+1:self.current_page+self.page_gap+1]
				return range(self.page_count+1)[self.current_page+1:]

				def page_list(self):
				return range(self.page_count+1)[1:]

				def page_html_format(self):
				html = '<div id="pagination">'
				if self.has_first():
				html += '<a href="?page=1">First</a>n'
				html += ''.join(['<a href="?page=%s">%s</a>n'%(n,n) for n in self.page_left_list()])
				html += '<a class="a1">%s</a>n'%self.current_page
				html += ''.join(['<a href="?page=%s">%s</a>n'%(n,n) for n in self.page_right_list()])
				if self.has_last():
				html += '<a href="?page=%s">Last</a>n'%self.page_count
				html += '</div>'
				return html

使用方法很简单

...
				PAGE_SIZE=10
				try:
				pagination = Pagination(results,PAGE_SIZE,current_page=int(request.GET.get('page', 1)),page_gap=10)
				except InvalidPage:
				raise Http404

				context = {
				'query': sTerm,
				'object_list': pagination.page_objects(),
				'pagination': pagination,
				}
				return render_to_response('search/search.html',RequestContext(request,context))
				...

模板使用

{{ pagination.page_html_format }}

效果如下(自己定义CSS)

免费手机天气预报

前段时间突然想研究飞信(fetion),因为觉得利用飞信发手机短信是个不错的方法.

于是就诞生了此程序,目前测试中 http://fengsms.appspot.com/ 大家可帮忙进行测试.

使用本程序用户需遵守2条原则

1. 必须是移动用户且绑定飞信,程序基于飞信,所以是免费的.具体可以参考飞信官网

2. 原则上只要是飞信好友,都可以通过此程序发送消息,建议不要乱加好友,否则会被移动认定垃圾短信导致封号(飞信号)

使用方法

1.注册   打开http://fengsms.appspot.com/ 左边即可注册.简单填写用户名和密码即可

2.登录   打开首页右边即可登录

3.输入手机号码和飞信口令. 这里声明,本程序的原理是模拟飞信登录,因此需要飞信口令,否则哪有免费短信一说,因此这里会记录用户的手机号码和飞信密码.本站不会想任何人透露.由于飞信是和手机绑定,因此只需要发送’新密码’到12520050即可重置密码.

4.输入后,请先点击’激活’按钮,如果担心密码输入错误,请点击旁边的’测试’按钮.如果有测试短信成功发送到手机,则口令正确

5.点上面导航条的’发送列表’.

6.在新增用户表单中输入带发送的手机号码和号码所在城市的拼音. 注意,系统默认不会给任何人发送天气预报包括自己,请把自己加入列表中.

7.可以点’立刻发送’按钮.测试是否收到当天天气情况.

 

注:程序测试中. 会出现不稳定情况,请各位海涵.

Linux(debian)下ffmpeg编译与运行

Why write this article?

   网上关于如何编译的文章很多,但有2个很明显的趋势

   1. 国内的大多东抄点西抄点,时间滞后不说,当你google的结果大部分都大同小异后就会有抓狂的感觉,究其原因还是国内站长们‘爬虫’太多.
   2. 国外优秀文章不错,很多,比如这篇 因此本文的目的主要是为了国内阅读英文较困难的同学服务,务必做到阅读完本文后,能自行编译ffmpeg.并简单操作.

Audience

    ffmpeg初学者,并对linux相关命令不了解

What is ffmpeg?

    简单来说就是一个跨平台、开源的流媒体处理工具.几乎集成了流媒体处理的所有功能,几乎’无所不能’.著名的’暴风影音’,’QQ影音’…都有’幸’加入了ffmpeg耻辱柱.

How to use?

    ffmpeg主要2种使用方式 1、命令行  2、使用lib库

    前者最方便,几乎不需要编程方面的知识,参考具体文档即可.

Compile

    因为ffmpeg是主要几乎linux开发且官方不提供现成的二进制文件,需要用户自行编译,这就大大增加了初学者入门的难度

    windows下有现成的编译库SDK,可以直接下载. 这里将如何在linux(debian)下编译ffmpeg.

    网上可以找到很多教程,在正式安装ffmpeg需要安装许多东西,其实那些都并不是必须的.比如lame

    Debian的确很强大,强大到不需要本文,只需要几个apt-get 命令即可实现整个过程.当然这里不是本文的重点,懒人可以直接用下面的代码直接安装二进制包,有兴趣的朋友继续看下文,我们来手动编译

    懒人方法::

apt-get install ffmpeg 如果提示不完整 继续输入 apt-get –f install

    手动编译:

1. 安装gcc编译器. gcc是linux下一个c的编译器,用来对c源码进行编译.使用 apt-get install gcc 下载
2. 下载ffmpeg源码包 wget http://www.ffmpeg.org/releases/ffmpeg-0.6.tar.gz wget是linux下比较方便的下载命令
3. 解压ffmpeg, tar zxvf ffmpeg-0.6.tar.gz 即可
4. cd ffmpeg-0.6 进入ffmpeg目录
5. 运行./configure –help 可以查看编译参数. 看看就可以了,具体详细参考这份文档.
6. 这里我们运行 ./configure --prefix=/home/fred/ffmpeg --enable-gpl --enable-shared 简单说下
--prefix指定编译后的路径,默认是编译到/usr /opt 等目录中去,个人不是很喜欢这种方式,初学者建议不启用该项.

--enable-gpl 启用gpl编码

--enable-shared 允许共享lib包

7. make 开始编译,看电脑情况,一般几分钟时间是要的.耐心等待吧

8. make install 把编译后的so,co这些二进制文件都转移到prefix指定的目录中去

    如果前面设置过prefix的朋友看这里,使用默认的可以忽略,这段作用是把ffmpeg执行命令加入到环境变量中去

 

$ cd /home/fred

$ vi .bashrc
插入 export ffmpeg=/home/fred/ffmpeg
export PATH = $ffmpeg/bin;$PATH

 

    到了这里,如果一切顺利的话,可以运行下面命令测试下

ffmpeg –-help

 

   如果打印出大量字符提示信息,那就说明安装正确了.

Example

    如果前面都没有问题,运行下面命令,这条命令作用是把flv转成mpg格式

 

ffmpeg -i kitty.flv -target ntsc-dvd -aspect 4:3 kitty.mpg

写个百度搬家玩玩

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

随便写了百度搬家工具打发下时间,这是从原来的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()