My Email: yeshengzou@gmail.com

显示标签为“Soluction”的博文。显示所有博文
显示标签为“Soluction”的博文。显示所有博文

前面通过Google Data API解决了光靠Email不能解决的标签和插图问题,自然,就想到应该可以插入LaTeX语法的数学公式吧,只是把这些公式转成图片插入就可以了。这中间只是多了一个自动编译并转为图片的过程,至少我之前是这么想的。

但在实际的操作中总有意想不到的问题,我第一次碰到了多线程或者多进程的问题。在之前写一些小东西的时候,是没有涉及过多线程或多进程的需求的,可在这里,去编译tex源文件的时候,它出现了。

最先我直接通过os.system把对tex源文件的编译写到某个函数中,可这样是无法执行的,我猜想应该是os.system还没有执行完,这个函数就返回了,而这个函数一返回,就把里面的os.system直接中断了。后来我用subprocessthreading来处理对tex源文件的编译,执行是没有问题了,但我无法在编译tex源文件处做阻塞,一阻塞就不能正常编译。不阻塞倒能正常编译,可我后继的操作必须在tex源文件编译完毕后才能进行,不能并发执行的。

最后这个问题我还是无解,我想可能与python是作为vim的脚本执行有关,这时python执行的这个进程与vim的进程的关系?所以我不得不把原本应该在函数内完成的事放到外部完成,虽然很dirty,但它能正常工作了。

import vim,os,markdown2,re,datetime

reInLineMath = re.compile(r'\$.*?\$')
reBlockMath = re.compile(r'\\\[.*?\\\]', re.S)

def getFileName():
    'get a random filename like 20090423'
    d = datetime.date.today().strftime('%Y%m%d')
    return d

def createTexFile(body, mathInLineList, mathBlockList):
    mathInLineList = '\n\\newpage\n'.join(mathInLineList)
    mathBlockList = '\n\\newpage\n'.join(mathBlockList)
    texcode = '''
                \\documentclass{article}\n
                \\usepackage{tikz}\n
                \\usepackage{amsmath}\n
                \\pagestyle{empty}\n
                \\\begin{document}
%s\n\\newpage\n%s\n
            \\end{document}''' % (mathInLineList, mathBlockList)
    file = open('/home/zys/temp/%s.tex' % getFileName(),'w')
    print >> file,texcode
    file.close()
    return file.name

subject = vim.current.buffer[0]
body = '\n'.join(vim.current.buffer[2:])

mathInLineList = reInLineMath.findall(body)
mathBlockList = reBlockMath.findall(body)

if mathInLineList.__len__() > 0 or mathBlockList.__len__() > 0:

    texFile = createTexFile(body, mathInLineList = mathInLineList,
              mathBlockList = mathBlockList)
    os.system('rxvt -e pdflatex --output-directory=/home/zys/temp/ %s' %
                                texFile)
    os.system('rxvt -e convert -trim  -density 120 -antialias %s.pdf %s.
              jpg' % (texFile.split('.')[0],texFile.split('.')[0]))

    mathList = mathInLineList + mathBlockList
    if mathList.__len__() == 1:
        body = body.replace(mathList[i],
            '![math](%s.jpg)' % (texFile.split('.')[0]))
    else:
        for i in range(mathList.__len__()):
            body = body.replace(mathList[i],
                '![math](%s-%d.jpg)' % (texFile.split('.')[0], i))

主要的代码就这些,用正则表达式从正文中取出tex相关的数学公式,然后把这些公式做成一个单独的tex源文件,一页一个公式,编译后得到一个pdf文件,用convert去把这个pdf文件转成jpg图片,这里带一个-trim参数,得到没有边距的图。如果是多页会得到一组编号的jpg图,再回头用这些图的本机地址去替换正文中的tex数学公式。

另外,代码高亮是通过highlight来做的,在vim中选中代码块,执行highlight就可以得到内嵌css的html带pre标签的代码。


下面纯属演示数学公式效果- -

八卦传播问题

假设某地区的总人口为math,在短期内不变,math表示知道消息的人数所占的百分比,初始时刻的百分比为math,传播率为math,另外有一部分人知道消息,但不传播,不传播率为math,则数学模型为:

math

求解得:

math

于是有:

math

此表明随时间的增长,消息慢慢地会淡化,逐步被人遗忘。

参考

<我的博客解决方案>中,最后有一些待解决的问题,昨天看了下Google Date API,算是解决了(主要是插图和标签的问题)。

标签问题

标签使用Blogger Data API是比较好搞定的,本身就有一个AddLabel函数。
import gdata.blogger.service
import atom

def postBlog(subject=None, body=None, labels=None, account=None,
           password=None):
  'to post blog via GData Blogger API'

  print 'To Post ...'

  client = gdata.blogger.service.BloggerService()
  client.ssl = True

  post = gdata.blogger.BlogPostEntry()
  post.title = atom.Title(text = subject)
  post.content = atom.Content(content_type = 'html', text = body)
  #post.AddLabel('Computer')
  if labels[0]:
      map(post.AddLabel, labels)

  try:
      client.ClientLogin(account, password)
  except gdata.service.BadAuthentication:
      print account, password
      print "ERROR: Login failed!!. (Wrong username/password?)"
      return False

  try:
      BLOG_ID = client.Get('/feeds/default/blogs').entry[0].
                GetSelfLink().href.split('/')[-1]
  except:
      print "ERROR: Can not get the BLOG_ID!!"
      return False

  try:
      client.AddPost(post, blog_id = BLOG_ID)
  except:
      print "ERROR: Can not add the blog!!"
      print "Is the format all right?"
      return False

  print "Blog `%s` post successfully." % subject2

注意,使用Blogger的API时,一定要使用安全链接(ssl = True),否则是接不上的。传说与GFW有关,昏!

插图问题

插图的问题是这样解决的:

  1. 通过正则表达式,从正文中获取所有插图的本地地址。
  2. 把这些图片通过Picasa Web Albums Data API上传到我的Picasa中指定的相册。
  3. 获取上传后,在Picasa中的这些图片的URL。
  4. 把正文中,所有图片的本地地址替换成Picasa中的URL。

-

import gdata.photos.service
import gdata.media
import gdata.geo

def uploadImages(filelist, account, password):
  '''Upload all images.
    And thd filelist is the re.findall() in blog.'''

  print "Upload All Images ..."

  try:
      gd_client = gdata.photos.service.PhotosService()
      gd_client.email = account
      gd_client.password = password
      gd_client.source = 'zys-blogimage-1'
      gd_client.ProgrammaticLogin()
  except:
      print 'ERROR: Could not Login in Picasa!!'
      return False

  album = gd_client.GetUserFeed().entry[1]
  album_url = '/data/feed/api/user/%s/albumid/%s' % (account,
              album.gphoto_id.text)

  replaceList = []

  for f in filelist:
      print "Uploading `%s` ..." % f[1]
      try:
          photo = gd_client.InsertPhotoSimple(album_url,
                  getFileName(), f[0], f[1],
                                              content_type='image/j
                                                             peg')
      except:
          print 'ERROR: upload %s failed!!' % f[1]
          return False

      replaceList.append((f[1], photo.GetMediaURL()))
      print "Completed. --> `%s`" % photo.GetMediaURL()

  print "All images have Uploaded."
  return replaceList

整理一下思绪,把当初的想法记录一下。

问题描述

建立一个博客发布平台,以便分享和记录自己的一些想法。

功能需求

  1. 在页面布局上基本兼容各种浏览器。
  2. 在页面主题上简洁、或可以让我完全自定义。
  3. RSS完全供稿。
  4. 自动投递,使我第一时间获取评论内容。
  5. 二级域名。
  6. 可以使用通用接口发布文章,Email或单独的API。
  7. 可以最大限度控制文章的格式,或直接支持使用HTML。
  8. 文章的保存有保证。
  9. 我可以用VIM写文章。
  10. 具备一定的分类管理功能。
  11. 访问速度不能太慢。

理想方案

打开VIM,写东西,发送。(自动发表、分类存档、备份源文件)

自己开发还是使用现成的?

自己开发的好处我可以完全控制所有的环节,随意添加我需要的功能,花点钱还能弄个顶级域名。但代价是,要花费比较多的时间,还要每年投入个几百元的主机费用。还有以后系统升级时可能非常折腾。而我现在又没很多的时间也没有钱,所以还是用一个现成的好。

用现成的我就选了Blogger。

实现方案

在VIM中如何发送?

一个比较通用方式是,在本机架设一个SMTP服务器,然后使用一个可以用VIM作编辑器的客户端,写好内容后本地投递。但这种方式太麻烦了,不但要一个独立的SMTP服务器,而且在写东西时你实际上还需要去打开一个客户端。

最简单的方式应该感谢gmail的开放API。因为gmail有开放的API,所以你使用这个API甚至可以把你的gmail账户当成是一个SMTP服务器。还有一个关键的因素就是,gmail有python的API,而VIM的脚本中是可以直接嵌入python的。剩下的事就比较简单了。

首先,从http://libgmail.sourceforge.net/下载libgmai

在VIM中使用libgmail直接发送邮件到指定地址(参考: http://djcraven5.blogspot.com/2006/10/send-gmail-message-from-vim.html):

" Make sure the Vim was compiled with +python before loading the
script...
if !has("python")
      finish
endif

:command! -nargs=? GMSend :call GMailSend("<args>")

function! GMailSend(args)
python << EOF
import vim
to = vim.eval('a:args')
GSend(to)
EOF
endfunction

python << EOF
########### BEGIN USER CONFIG ##########
account = 'xxxx@gmail.com'
password = 'xxxxx'
########### END USER CONFIG ###########

def GSend(to):
  """
   Send the current buffer as a Gmail message to a given user.
   """
  import libgmail

  subject = vim.current.buffer[0]
  attachments = vim.current.buffer[2].split(',')
  if attachments[0] == 'None': attachments = None
  body = '\n'.join(vim.current.buffer[4:])

  ga = libgmail.GmailAccount(account, password)
  try:
      ga.login()
  except libgmail.GmailLoginFailure:
      print account, password
      print "Login failed!!. (Wrong username/password?)"

  gmsg = libgmail.GmailComposedMessage(to, subject, body, filenames
         = attachments)

  result = ga.sendMessage(gmsg)

  if result:
      print "Message sent `%s` successfully." % subject
   else:
      print "Could not send message."

EOF

格式如何控制?

Blogger中可以直接使用HTML,所以直接发送HTML格式的邮件就可以了。

但是,如果直接写HTML不是太折腾了吗?所以我想用一种wiki的语法来写,然后解析成HTML后发送出去。最先考虑的是用与MoinMoin一样的语法,不过MoinMoin中似乎并没有把它的语法parser分离出来,google了一下,也有人对此进行了相关的探索,但我没找到比较圆满的结果。于是我决定使用markdown,它比较简单,网上相关的扩展实现也不少,使用面还是很广的,重要的是它有python的实现,可以从这里下载(http://pypi.python.org/pypi/markdown2/)。

markdown2只有一个文件,使用非常简单:

>>> import markdown2
>>> markdown2.markdown('*syntax*')
u'<p><em>syntax</em></p>\n'
>>>

要在VIM中正常使用markdown2解析后的结果,需要对结果进行一次utf8的编码。

body = markdown2.markdown(body).encode('utf8')

然后对于解析后得到的HTML结果,可以先生成一个本机的临时文件,在本地浏览器中预览一下。

file = open('/home/zys/temp/' + subject + '.html','w')
print >> file,body
file.close()

cmd = 'firefox /home/zys/temp/%s.html' % subject
os.system(cmd)

备份源文件

每一篇文章的markdown2格式的源文件,都在发布文章的同时发送到我指定的邮箱当中保存。

file = open('/home/zys/temp/' + subject + '.markdown', 'w')
print >> file,source
file.close()

if not attachments: attachments = []
attachments.append('/home/zys/temp/' + subject + '.markdown')

gmsg2 = libgmail.GmailComposedMessage('xxxxx@gmail.com',
'[带着梦想走天涯]' + subject, body, filenames = attachments)

TODO

经过上面提到一番折腾后,已经可以比较顺手地使用了,但还有一些比较麻烦的问题还没有解决。

  • 在文章中插图。这点的麻烦之处在于自动上传图片。如果在邮件当中添加图片附件,那么这些图片会被自动上传到picasa中,同时自动在文章的最前面插入这些图片,只是最前面,你不能把它插入到文章的其它部分中。如果在文章中间手动使用HTML标签插入图片,那么需要自己先将图片上传,获得URL后才能进一步操作。其实在gmail中已经可以自由插图,系统会自动上传,但在本机的VIM中,如何在邮件中自由插图我还无解T_T。这个在文章中间插图的需求还影响到其它一些功能的实现,如使用LaTeX的语法写一些公式或画一些图,本来可以自动转成图片插入到HTML页面中的。

  • 为文章添加标签。很遗憾,通过邮件方式发布文章,我就是不知道怎么添加标签,google也无结果。

  • markdown2的hack。把markdown2改成尽量接近MoinMoin的语法,还要给它添加表格的相关语法,因为直接用HTML写一个表格还是比较烦的。

结束语

反正现在使用这个解决方案还是可以说比较顺手的。接下来会去看一下Blogger Data API,看能不能解决存在的问题。

较旧的博文 主页