2009年3月30日 星期一

PyPdf 讀取中文Pdf亂碼問題

最近找論文資料常常會下載一堆相關題目的pdf檔然後慢慢消化,不過這樣實在是很浪費時間,所以週末就想說寫一隻程式搜尋資料夾中所有pdf,然後給它關鍵詞,最後能夠顯示這些關鍵詞在哪幾篇pdf的第幾頁中,如此一來就省事多了。

python的好處就是擴充套件多如過江之鯽,當然光pdf就好多個,這裡挑選的是PyPdf.

安裝完成之後先以取出內容文字為主寫出一段程式測試,測試pdf為中文big5編碼,但除了標題encode("big5")能夠正常顯示中文外,內容卻是一片亂碼,於是把每段文字拆解成char再使用hex code列印出來...

0xb8 0xea ... 這不是big5的"資"嗎?表示編碼是正確的阿!為何print就是有錯誤?

於是我使用一個範例字串 zh = "\xb8\xea" ,print出來是"資"沒錯,但 u"\xb8\xea" 加上unicode就會和上面呈現一模一樣的亂碼。原來PyPdf中PageObject extractText()會將所有內容編碼成unicode,所以我們要把unicode反解回來 str.encode('latin-1') ,嗯正常了^^。

#!/usr/local/bin/python
# -*- coding: utf-8 -*-

from pyPdf import PdfFileReader

input = PdfFileReader(file("infosafe.pdf", "rb"))

# Show title from this pdf.
print input.getDocumentInfo().title.encode("big5")

# Total pages.
pages = input.getNumPages()

# Loop to print content.
for i in range(0, pages):
    pageObj = input.getPage(i)
    str = pageObj.extractText()
    
    # The extracted text has been set to unicode, therefore, we should transfer it's format to the normal 'latin-1'.
    print str.encode('latin-1')
    
    """
    # Print hex code.
    for j in range(0, len(str)):
        print hex(ord(str[j]))
    
    break
    """
"""
# This is an example.
zh = u"\xb8\xea".encode('latin-1')
print type(zh)
print zh
"""

2009年3月26日 星期四

妙事一籮筐

這幾天真的很妙~

前天收到一個加拿大台灣留學生請我幫忙寫他們教授出的python作業

今天早上iCloud CEO也發了一封信請我幫忙翻譯(當然不是只有我啦, 還有很多其他中國地區使用者)

內容大概是這樣

算是為了這周平凡無奇的生活添加一點樂趣^^

2009年3月25日 星期三

Python RssParser with MySQL

其實繼上次寫了python資料型態上下集之後,這次應該來寫一下迴圈與條件式等的教學,但是其實那些東西都是廢話,我下一次再把一些注意事項放上來就好了!不然難道你認為if條件式會寫成怎樣??

這次開始從實例下手,之前我寫過Java RssParser,是儲存成檔案的方式,現在用python教大家如何parse Google RSS新聞檔並儲存 發布時間、標題、連結、相關內容 等資訊到MySQL中。

把玩這支程式之前請先安裝兩個函式庫,feedparserMySQLdb(說明)。裡頭都有安裝說明與教學。

By the way, 我的python是2.5版

sql -- 建立資料庫並使用SQL新增下列資料表

CREATE TABLE IF NOT EXISTS `FEED_MSTR` (
 `ID` int(11) NOT NULL AUTO_INCREMENT,
 `DATE` datetime NOT NULL,
 `TITLE` varchar(255) CHARACTER SET utf8 NOT NULL,
 `LINK` text CHARACTER SET utf8 NOT NULL,
 `SUMMARY` text CHARACTER SET utf8 NOT NULL,
 PRIMARY KEY (`ID`),
 KEY `DATE` (`DATE`,`TITLE`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

RssParser.py

#!/usr/local/bin/python
# -*- coding: utf-8 -*-

# Copyright (C) 2009 Kakapo Studio.
# Author: Sam Wang
# Contact: sam.wang.0723@gmail.com

""" This program can parse any RSS or Atom type file on the internet and put it into database. """

import feedparser
import datetime
import MySQLdb

from time import mktime 

data = feedparser.parse(r"http://news.google.com.tw/news?pz=1&ned=tw&hl=zh-TW&topic=t&output=rss")

conn = MySQLdb.connect(host="localhost", user="root", passwd="********", db="YOUR_DATABASE", charset="utf8")
cursor = conn.cursor()

# Loop to get data.
param = []
for item in data.entries:

   # Make tuple to timestamp.
   ts = mktime(item.updated_parsed)
   # Transfer to datetime format.
   dt = datetime.datetime.fromtimestamp(ts)

   ntime = dt.strftime("%Y-%m-%d %H:%M:%S")
   ntitle = item.title.encode('utf8')
   nlink = item.links[0].href.encode('utf8')
   nvalue = item.summary_detail.value.encode('utf8')
  
   # Insert into param.
   param.append((ntime, ntitle, nlink, nvalue))

# Write to database.
sql = "insert into FEED_MSTR(DATE, TITLE, LINK, SUMMARY) values(%s,%s,%s,%s)"
cursor.executemany(sql, param)
  

cursor.close()
conn.close()

稍微說明一下 cursor.executemany(sql, param) 那段,executemany可以用字串當樣板然後給他list或tuples動態給予參數,假設一次update 3筆資料, 每筆有2個欄位, list儲存方式要像如此[(x,x) , (y,y), (z,z)]...這樣update時就會分開成len(list)的執行次數, 每次update len(list[i])個欄位了

2009年3月24日 星期二

最新十大透支健康行業

轉載自http://big5.xinhuanet.com/gate/big5/news.xinhuanet.com/health/2006-08/18/content_4977708.htm

很高興IT業榮獲榜首...說這句話的同時壽命又少了0.01歲...

但是國外工程師好像都很悠閒, 每天穿短褲, 到處有零食與電動...而且人家的創意與技術就是比我們強...
總有一天我也要打造這樣的環境...

健康透支十大行業依次為:

1、IT
2、企業高管(含民營企業主)
3、媒體記者
4、證券
5、保險
6、出租車司機
7、交警
8、銷售
9、律師
10、教師
調查發現,精神壓力過大,生活節奏過快,飲食和生活不規律,是這十大行業的人群嚴重透支健康的主要原因。

關于壓力來源,31%的受調查者反映最大的壓力源自家人,19%的人反映是性生活。受調查者認為,面對源自領導同事和經濟生活方面的壓力,未婚青年面對創業、婚姻的擔憂,已婚人士頭頂巨額按揭房款和教育支出,只能繼續透支健康。

2009年3月19日 星期四

不知道要下什麼標題

就像美國總統歐巴馬一樣面對AIG發放紅利氣到嗆到, 今早我也發生了一樣的事, 剛出門騎車就拋錨所以只好等附近的機車行開門就把車牽過去麻煩他修一下...以下為對話(對方可能不是老闆但我還是叫老闆):

我: "老闆, 我機車掛點了可以幫我看一下嗎?"
老闆: "...."(準備開店中...)
我: "老闆, 我把機車推上去歐"(把機車推到維修區)
老闆: "你推上去幹麼...我有叫你推上去嗎?"
我: "...拍謝"(把機車倒退回去)
我: "請問大概什麼時候能好?"
老闆: "要等啦!你先留你的聯絡方式"
我: "不能幫個忙先看一下嗎?我等等還有事"
老闆: "急什麼, 留下機車鑰匙修好在和你說!"
我: "..."(留下鑰匙默默走人)

走掉得路上我越想越氣...媽的...我是叫你修免費的歐!長得一副好像我欠他的樣子!

後來中午接到電話回去看換下來的零件, 變成一個比較菜的技師在修, 態度很好也會和我說哪裡燒壞等等還會指給我看...早上那個王八蛋在一旁看電視...我當然是青了他一下...不過他好像沒看到。

這件事讓我回想到以前當兵的時候, 我是二級廠補給士, 想當然爾各連的裝備都是要找我補料或更換, 自然權力就很大, 尤其是老了之後, 別連要上來申請料件都還要帶吃的喝的才行, 那時候的我在他們眼中一定也是這樣, 而我去聯保廠的時候對學長姐也是差不多, 好像是一種風氣吧!差別只在於他們修裝備不需要付錢而已, 是國家出。

這件事氣歸氣...反正只要車子修好了就好~我還向那個菜鳥技師要了電話以後只找他修

2009年3月9日 星期一

PHPMailer utf-8郵件主旨亂碼問題

日前使用PHPMailer發送utf-8格式的中文郵件時, 發現收件夾內接收的郵件均為亂碼, 而且連帶影響到郵件的html內文, 原因在於E-Mail標準格式中表頭的部分不允許使用雙位元的文字(也就是中文等...), 所以必須使用mb_encode_mimeheader()函式將雙位元文字編碼為單位元字串。

但是因為mb_encode_mimeheader()預設的字串編碼為西方ISO-8859-1, 所以如果你的編碼中文字為UTF-8就必須使用mb_internal_encoding()將內部預設編碼改為UTF-8。

<?php
mb_internal_encoding('UTF-8');    // 內部預設編碼改為UTF-8
$mail->Subject = mb_encode_mimeheader($_POST['title'], "UTF-8");
$mail->Body = $_POST['content'];
?>

2009年3月6日 星期五

研究開發iPhone應用程式

最近和歐拔聊天, 想說來玩一下iPhone的開發, 雖然我自己去年就買了G1 Dev版, 本來要加入Android的行列, 但好死不死今年又買了MacBook而且實在逃不出它的魔掌...

首先要先從Objective-C開始學, 基本上宣告和一些寫法有點差異, 但畢竟大體上結構差不多, 只是又要自己管理記憶體有點煩就是了, 畢竟Java寫久都覺得釋放記憶體這種動作應該是VM應該做的吧~

最近也找了蠻多相關文件, 但是早上這個讓我比較興奮, 是史丹福大學的iPhone開發課程講義耶!http://www.stanford.edu/class/cs193p/cgi-bin/index.php, 裡面的程式碼與pdf都可以下載來用, 網路真是太棒了

2009年3月4日 星期三

Python 資料型態(下)

4. Dictionaries -> Dictionaries擁有鍵與值的對照, 類似Java中的Map類

>>> demo = {'a':123, 'b':456, 'c':789} # 使用“:“分隔鍵與值
>>> demo['a']
123

當然也可以不必在一開始就做指定動作, 能夠在不同位置指定內容讓Dictionaries擁有了極大的彈性

>>> demo = {}  #  指定一個空殼給demo
>>> demo['a'] = 123
>>> demo['b'] = 456
>>> demo
{'a' : 123, 'b' : 456}

巢狀內容的呼叫

>>> demo = {'name':{'first':'Bob', 'last':'Smith'},
      'job':['dev', 'mgr'],
      'age':40.5}
>>> demo['name']['first']
'Bob'

依照鍵值排序顯示內容:事實上我們可以發現Dictionaries顯示出的內容並不會從左到右排序, 所以有以下方法可供參考

>>> D = {'a':1, 'c':2, 'b':3}
>>> Ks = D.keys()
>>> Ks
['a', 'c', 'b']
>>> Ks.sort()
>>> Ks
['a', 'b', 'c']
>>> for key in Ks:
   print key, '=>', D[key]
a => 1
b => 2
c => 3

上面的方法是先取出鍵值陣列排序在依序取出值, 但還有一種更簡單的方式就是使用內置的sorted()方法

>>> for key in sorted(D):
    print key,'=>',D(key)
a => 1
b => 2
c => 3

5. tuples -> tuples 是python中一個特別的元件, 你可能不曾在別的語言中碰過, 它類似List但卻無法更動順序, 也無法在宣告之後指定參照

>>> T = (1, 2, 3, 4)
>>> len(T)
4
>>> T + (5, 6)
(1, 2, 3, 4, 5, 6)
>>> T[0]
1
>>> T[0] = 2   # 如果想指定參照會出現Exception

Traceback (most recent call last):
 File "<pyshell#4>", line 1,in <module>
   T[0]=2
TypeError:'tuple' object does not support item assignment

事實上tuples並不像List那麼常被用在練習中...但是tuples的好處就是在於"不可更動性"

6. Files -> 檔案操作物件通常一般不會包含在核心物件之內, 古怪的是你無法使用敘述式建立它們, 唯一的方法只有呼叫open()函式

寫入資料

>>> f = open('data.txt', 'w')    #開啟data.txt, 'w'為寫入write模式
>>> f.write('Hello\n')       # 寫入字串
>>> f.write('world\n')
>>> f.close()      # 關閉檔案flush剛剛寫入的資料

讀取資料

>>> f = open('data.txt')  # 也可以在型態上加上'r'
>>> data = f.read()  # 讀取函式read(), 但其實也可以使用 for text in f 來讀
>>> data
'Hello\nworld\n'
>>> print data
Hello
world

其他還有一堆類似Files物件的工具, 譬如pipes, fifos, sockets, keyed-access files, object persistence, descriptor-based files, relational and object-oriented database interfaces等, 以後陸續有學習到再做介紹。

Python 資料型態(上)

Python 有一個特性, 就是變數的宣告不需要使用強型態, 你可以指定 a = 2, 也可以在下一行改變成 a = 'sample', 包括陣列存放都可以使用多種不同型態的變數例如 a = [123, 'abc', 1.23]。

介紹一下 Python 核心物件內含的資料型態

1. Numbers -> 整數(integer), 含小數的數字(floating-point numbers), 另外像是一些長整數(unlimited-precision “long” integers), 複雜的數字(complex numbers)與固定精度的小數(fixed-precision decimals)等...。

範例:

>>> 123 + 456   # 整數相加
579
>>> 1.5 * 4    # 小數運算
6.0
>>> 2 ** 100   # 2的100次方
1267650600228229401496703205376L

另外有一些有趣的功能, 例如把一個高精度的小數用 print 顯示的話, 用戶只會看到部份好辨認的位數

>>> 3.1415 * 2  # 完整精度
6.2830000000000004
>>> print 3.1415 * 2 # 使用者好觀看的數字
6.283

Learning Python (Oreilly 出版) 的作者Mark Lutz說道 if something looks odd, try showing it with a print statement. (如果某樣東西看起來很莫名奇妙, 請嘗試使用print將它顯示出來)

2. Strings -> 字串, 基本上你可以將字串敘述成多個字元組合成的陣列, 譬如 'Spam' 就等於一個 ['S', 'p', 'a', 'm']。

範例:

>>> S = 'Spam'
>>> len(S)   # 字串長度
4
>>> S[0] # 該字串的第一個字元
'S'
>>> S[1]  # The second item from the left
'p'

也可以使用另外一些方式取出字元

>>> S[-1]  # 最後一個字元
'm'
>>> S[len(S)-1]  # 用總長減去一(麻煩的作法)
'm'

如果要取出範圍

>>> S[1:3]  # 取出從第一個到從頭數第三個
'pa'
>>> S[1:]  # 第一個字元以後
'pam'
>>> S[:-1]  # 最後一個字元以前
'Spa'

Python 中字串也可以用乘法運算

>>> S * 8  # 重複顯示8次
'SpamSpamSpamSpamSpamSpamSpamSpam'

字串相加

>>> S + 'xyz'  # 字串合併
'Spamxyz'

另外字串也有一些相關函式

>>> S.find('pa')   # 找尋比對字串出現位置
1
>>> S
'Spam'
>>> S.replace('pa', 'XYZ')   # 取代 'pa' 為 'XYZ', 但請注意原本字串不會被更動
'SXYZm'
>>> S
'Spam'
>>> line = 'aaa,bbb,ccccc,dd'
>>> line.split(',')  # 拆解字串為陣列
['aaa', 'bbb', 'ccccc', 'dd']
>>> S.upper( )  # 轉為大寫
'SPAM'
>>> line = 'aaa,bbb,ccccc,dd\n'
>>> line = line.rstrip( )   # 去除右方空白字元, 如同trim()
>>> line
'aaa,bbb,ccccc,dd'

3. List -> 集合, 不需指定長度並可容納不同型態的物件

>>> L = [123, 'spam', 1.23]
>>> len(L)  # List 長度
3
>>> L + [4, 5, 6]   # 串接List
[123, 'spam', 1.23, 4, 5, 6]
>>> L.append('NI')   # 新增一個元素到最後面
>>> L
[123, 'spam', 1.23, 'NI']
>>> L.pop(2)   # 將L[2]移除並返回值
1.23
>>> L      # "del L[2]" 一樣可以達成刪除目的
[123, 'spam', 'NI']
>>> M = ['bb', 'aa', 'cc']
>>> M.sort( )   # 正向排序(小到大)
>>> M
['aa', 'bb', 'cc']
>>> M.reverse( )  # 反向排序(大到小)
>>> M
['cc', 'bb', 'aa']

巢狀List

>>> M = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

>>> M[1]
[4, 5, 6]
>>> M[1][2]
6

還有一點蠻有趣的就是在中括號內寫迴圈與條件式, 個人認為能省下很多行程式碼的寫法

>>> col2 = [row[1] for row in M]  # 取出M中每一個元素的第1個元素(0,1,2...)
>>> col2
[2, 5, 8]

>>> [row[1] + 1 for row in M]  # 取出M中每一個元素的第1個元素並加上一
[3, 6, 9]

>>> [row[1] for row in M if row[1] % 2 == 0] # 判斷元素中2的倍數
[2, 8]

未完待續...

2009年3月3日 星期二

什麼是 Python?

Python的創始人為Guido van Rossum。在1989年聖誕節期間的阿姆斯特丹,Guido為了打發聖誕節的無趣,決心開發一個新的指令碼解釋程式,作為ABC語言的一種繼承。之所以選中 Python(大蟒蛇的意思)作為程式的名字,是因為他是一個Monty Python的飛行馬戲團的愛好者。

就這樣,Python在Guido手中誕生了。實際上,第一個實作是在Mac機上。可以說,Python是從ABC發展起來,主要受到了Modula-3(另一種相當優美且強大的語言,為小型團體所設計的)的影響。並且結合了Unix shell和C的習慣。

雖然 Python 可能被粗略地分類為「指令碼語言」(script language),但實際上一些大規模軟體開發計劃例如 Zope、Mnet 及 BitTorrent,Google 也廣泛地使用它。 Python 的支援者較喜歡稱它為一種高階動態編程語言,原因是「指令碼語言」泛指僅作簡單編程任務的語言,如 shell script、JavaScript 等只能處理簡單任務的編程語言,並不能與 Python 相提並論。

此外,由於 Python 對於 C 和其他語言的良好支援,很多人還把 Python 作為一種「膠水語言」(glue language)使用。使用 Python 將其他語言編寫的程式進行整合和封裝。 在 Google 內部的很多專案使用 C++ 編寫性能要求極高的部分,然後用Python叫用相應的模組。

Python是一門跨平台的指令碼語言,Python規定了一個Python語法規則,實作了Python語法的解釋程式就成為了Python的直譯器,我們用的比較多的是C版本的Python,也就是使用C語言實作的Python直譯器,除此之外還有使用Java實作的Jython和使用.NET實作的 IronPython,這些實作可以使Python使用者充分利用己有的Java及.NET資源。

同時,Python支援幾乎所有常用的作業系統,包括:Windows/DOS、Macintosh、Linux 及 FreeBSD。及很多不常用的作業系統,包括AIX、AS/400 (OS/400)、BeOS、OS/2、OS/390與z/OS、Palm OS、PlayStation與PSP、Psion、QNX、RISC OS、Series 60、Sparc Solaris、VMS、VxWorks、Windows CE或Pocket PC、Sharp Zaurus、MorphOS等。

可擴充性可說是Python作為一種編程語言的特色。新的內置模組(module)可以用C 或 C++寫成。而我們也可為現成的模組加上Python的介面。Python可以使使用者避免過分的語法的羈絆而將精力主要集中到所要實作的程式任務上。

因此Python具有非常龐大的程式庫,透過它們可以快速完成絕大部分常用的任務,如:從某個URL中獲取資訊、正則運算式、獲得某個檔案或字串的MD5特徵字串、多執行緒、XML及HTML的分析等。

Python也被稱為是一門清晰的語言。因為它的作者在設計它的時候,總的指導思想是,對於一個特定的問題,只要有一種最好的方法來解決就好了

摘錄自http://zh.wikipedia.org/w/index.php?title=Python&variant=zh-tw

2009年3月2日 星期一

HTML 5.0

W3C據說2004年就開始推動5.0草案, 但是我想根本沒有什麼人知道這件事, 直到最近Apple Sarfari 4 beta版釋出之後, 看見其中新功能支援HTML5.0影音標籤才赫然驚覺。Google一下才知道5.0是近期最大的改版行為, 目標是在2010年之前,HTML 5的正式版將面世,目標是把這種超文字標示語言(markup language) 帶往今天的豐富媒體網路環境,以新型的應用程式設計介面,控制影音內容。

其中一些改變例如引入了一整套全新的元素來讓構建頁面變得更加簡單與直接使用video, audio之類的標籤描述影像與音效嵌入等...詳細資訊可以參考這篇http://www.wowbox.com.tw/blog/article.asp?id=2446

最近剛好也寫到一篇報告, 內容是有關數位出版, 大部分的權力也是被西方組織或是出版社壟斷, 甚至積極想鉅資吞食華文市場。 所以我的夢想是希望華語地區的人也能團結(雖然中國人真的有夠鬆散), 我們也來創立一個組織, 擁有以華文為主的標準, 讓外國人學中文學到欲哭無淚...哈哈