顯示具有 Python 標籤的文章。 顯示所有文章
顯示具有 Python 標籤的文章。 顯示所有文章

2015/07/19

Python 爬蟲程式框架 Scrapy

  自從上一篇和爬蟲相關的文章:Web 測試及網路爬蟲的工具 Splinter 之後就沒有再寫相關文章,最近在思考一些軟體系統架構時想到為何蟲功能不能也這樣想?找了一下果然國外強人就有這樣的作品分享,趕緊來分享一下這個Python 開發的framework: Scrapy

 

2014/11/16

Python 與 Ruby 的心得

  因為工作的關係這陣子與Python和Ruby 有了相當程度的接觸與運用,和之前自己比較熟悉的Java自然會拿出來比較一番。這兩個 Script language 本質上當然和Java不同。但它們可以做的事大方向上是相同的,只是偏好上的不同。單就語法上來看,我比較喜歡Ruby。但就應用廣度來看Python就比較吃香,例如:OpenStack , Django和Blender及Maya等一些3D建模軟體的應用。相對來看Ruby在資源上真的比較不足。只是因為Sketchup 3D 建模軟體中的plugin 使用的語言是 Ruby,讓我有機會接觸到它,也因此去了解了它在Web Application 上的framework Ruby on Rails.在台灣Ruby真的相對來說使用Ruby的人及公司真的很少,在技術人力的尋找會比較困難.但單就技術上的學習來看其實它很容易學習,只要有其它語言的基礎,真的不是什麼難事.

  Python用了一陣子下來,個人覺得其語法的縮排雖然是為了精簡程式碼,省去括號的使用。但這也是常讓我困擾的地方,其它方面倒是沒什麼意見。因為OpenStack 的關係,現在企業開始有一些Python及OpenStack 的人力陸續開出來.

Ruby 語法上真的很吸引人,短短兩三天它就讓我著迷。若不是工作的關係真的不會想主動去學它,但學了就會愛上它,只可惜它的競爭對手太多了,近年來Scala及JavaScript 的火紅多少影響它的發展。特別是JavaScript ,在Node.js 技術出來之後讓Web 前後台開發的語言統一了,這真是Web 開發工程師的一大福音.

接下來列幾個自己覺得Ruby 語法對學過其它語言轉過來的人要特別注意的地方:

語法中程式區塊省去括號的使用:

if ....
    puts 'Hello'
    puts 1+2
end

class  Car
    def run
    end
end

case ...
   ...
when ...
   ...
end

for num in (1..3)
    puts num
end


字串與數字的串接 : 

irb(main):001:0> s1 = 'Hello'
=> "Hello"
irb(main):002:0> puts s1 + 100
TypeError: can't convert Fixnum into String

irb(main):003:0> puts s1 + 100.to_s
Hello100
=> nil

就以上的程式片斷來看,和其它語言不同的是數字與字串不能直接串接, 需要先將數字轉成字串.

陣列元素型態與相加:
    Ruby陣列中的元素可以是不同資料型態
    Ruby兩個陣列可以使用加號(+) 直接串接形成一個合併後的新陣列

類別/繼承/存取控制:
      class Child < Parent
           def print
                puts 'I am Child'
           end

           def dump
           end

           private : dump

      end
     
      Ruby 的類別沒有多重繼承, class 間的繼承使用一個小於(<) 符號,夠簡單也夠簡潔. method 預設是 public ,不需像Java那樣前面加個 public 來宣告. 但 private method 就得特別宣告

變數:
     Ruby 變數不需要宣告型別,但變數名稱第一個字元卻可以很容易區分其範圍(scope)

$ 全域變數 (global variable)
@ 實例變數 (instance variable)
[a-z] 或 _ 區域變數 (local variable)
[A-Z] 常數

註解(comment):
     單行註解使用 # 開頭
     多行註解使用 =begin 開始, =end 結束,這點倒是不太簡潔

Ruby 還有一堆方便簡潔的語法, 等有空再整理,也當做自己的備忘錄.






2014/10/12

Python 另人頭痛的 Singleton 問題

  最近學習使用Python 寫網路爬蟲程式,除了一些動態及需要輸入查詢條件的網頁問題外,最惱人的還是在Python 語法上,因為對Java 較熟悉,程式撰寫習慣會以OO的方式做思考,所以將一些Python 程式碼要重構時發現光一個Singleton pattern 的寫法就夠人煩的了,在Java 中是簡單的不得了,  在Python 中卻是寫法好幾種,重點是不夠簡單易懂。請參考 Stack Over Flow 網站上以下這篇討論:

 Creating a singleton in Python

以下是其中一種個人認為比較簡單的方法,缺點是無法避免被誤繼承的問題,但還不致於造成大問題。

class Singleton:
    __single = None
    
    def __init__(self):
        if Singleton.__single:
            raise Singleton.__single
        Singleton.__single = self
        self.name = None
        
    def __str__(self):
        pass
    
    def dump(self):
        if self.name == None:
            print ''
        else:
            print "Name : " + self.name
        
    def setName(self, name):
        self.name = name
        
    def getName(self):
        return self.name
        
class WorldSingleton(Singleton):
    pass

  個人是習慣使用Eclipse 搭配 PyDev 這個plugin 來開發 python 程式,以上程式碼無法在開發時就先警告,要到執行階段才能發現。

2014/09/27

Python 日期時間運用

  開始認真學起Python這個強大的script language ,因為它可以幫我運用在許多方面,像是Blender / Panda3D / Web scraping 等等。拿來運用時就想到以前在用 Java 時都用建立一套日期及時間的 utility library , 現在語言換了,應該也要先熟悉它如何處理日期及時間,以下整理自己常用的用法:

from datetime import date, time,datetime

# 取得今天日期
today = date.today()

# 日期 減一天
dt = today.replace(day=today.day-1)
print dt.year,dt.month,dt.day
# 月份 加一個月
dt = today.replace(month=today.month+1)
print dt.year,dt.month,dt.day
# 年份 加一年
dt = today.replace(year=today.year+1)
print dt.year,dt.month,dt.day
# 年/月/日 各減一
dt = today.replace(year=today.year-1, month=today.month-1, day=today.day-1)
print dt.year,dt.month,dt.day

以上這個年/月/日加減是有問題, 特別是當該日期為某月第1天時, 使用 day=today.day - 1 會出現以下 exception :

 >>> yesterday = date.today().replace(day=today.day-1)

Traceback (most recent call last):
  File "", line 1, in
    yesterday = date.today().replace(day=today.day-1)
ValueError: day is out of range for month


這時候該使用 timedelta , 請看以下示範:

>>> from datetime import date, datetime, timedelta
>>> tomorrow = datetime.now().date() + timedelta(days=1)
>>> print tomorrow
2014-10-02
>>> print datetime.now().date()
2014-10-01
>>> yesterday = datetime.now().date() + timedelta(days=-1)
>>> print yesterday
2014-09-30



# 輸出格式變化
print dt.strftime("%y%m%d")
print dt.strftime("%y/%m/%d")
# 年份為四位西元年 %Y
print dt.strftime("%Y%m%d")
print dt.strftime("%Y/%m/%d")
print dt.isoformat()

# 取得現在日期時間
now = datetime.now()
print now
# 印出現在的 時:分:秒
print now.strftime("%H:%M%S")
# 印出現在的 西元年月日 YYYYMMDD
print now.strftime("%Y%m%d")


前半部日期的加減是個人覺得很實用的一部份,可以用來一天天推移。從這些程式碼片斷可以看出來Python簡單卻很有威力的地方。換成其它語言可能要寫一堆程式碼才能達成相同的功能。

2014/09/24

Web 測試及網路爬蟲的工具 Splinter

  最近在研究如何自動化到一些網站抓資料,一開始某些靜態網頁比較簡單,不管是用Java 或 PHP 都可以抓下來。但遇到一些使用 JavaScript / AJAX 及網頁會重導到其它頁的動態網頁真的是沒法子,特別是一些還要輸入日期或其它資料的表單網頁。參考了"網路機器人,網路蜘蛛與網路爬蟲 PHP/CURL 程式設計指南"這本書中介紹的工具 iMarco ,但仍無法全自動化。接下來把腦筋動到要用 C# 來控制 IE (Internet Explorer) ,可是時間上不允許,只好再找工具,最後找到了 Splinter 這工具,它其實預設是搭配Selenium 這個 web 測試自動化工具,雖然 Selenium 這個工具有 FireFox plugin , 也有 IDE ,Splinter 才能真正做到全自動化。

     根據官方網站(http://splinter.cobrateam.info/)的介紹,它是一個 open source 工具,用來測試 web 應用程式。使用的語言是 Python。可以讓你自動化瀏覽器的行為,例如:變換網址 (URL)及與網頁互動。

    這裡先介紹在 Windows 平台如何安裝,Linux / Mac OS 比較簡單:
  1. 先到 Python 官網(http://www.python.org)下載 Python 來安裝 , Python 2, Python 3皆可
  2. Google 找一下 get-pip.py ,下載到自己指定目錄
  3. 執行 python get-pip.py 將 pip 安裝起來
  4. 安裝 splinter : 執行 python -m pip install splinter
以上步驟完成後就可以參考 splinter 官網中的範例來測試一下。目前我在 Windows 7 中安裝的是 Python  2.7.8,執行以下程式片段可以執行 FireFox 連上 Yahoo 奇摩,還可以自動輸入關鍵字"CSS3"搜尋成功。


from splinter import Browser
b = Browser()
url = "tw.yahoo.com" b.visit(url); url = "http://tw.yahoo.com"
b.visit(url)
b.fill('p', 'CSS3')
btn = b.find_by_id('searchsubmit')
btn.click()



    當然,前題是要對 html 及 Python 有點了解才能發揮 splinter 的功能。能自動輸入與網站互動後找到所要的網頁資料才只是第一步,資料能取回來存放才是後續的工作重點。在尚未找到 splinter 之前,也使用過 crawler4j 及 Scrapy ,現在終於有個簡單的工具可用了,後續會再介紹一些實例。

安裝 get-pip.py 訊息:
D:\download>python get-pip.py
Downloading/unpacking pip
Downloading/unpacking setuptools
Installing collected packages: pip, setuptools
Successfully installed pip setuptools
Cleaning up...

    不建議使用 IE,預設使用FireFox , 若沒有安裝 FireFox 也請先將它裝好,官方網站說也可以使用Chrome 及 IE,但在Windows 下尚未試成功。也不建議在 Windows cmd.exe 下執行 python.exe 會有編碼問題,請使用 IDLE。或是先使用 chcp 將 code page 先改成 utf-8,在Linux 中沒有這個困擾,或是可以使用Eclipse 安裝 PyDev plugin。在Eclipse 中開發Python 程式是很愉快的。

    當然直接使用 Selenium 可以配合其它程式語言如: C#及 Java,但仍然不如使用 Python 這種script language 來得好用,為使麼呢?因為每次遇到一個新的網頁要爬資料時,都會先開啟瀏覽器檢視網頁原始碼的功能,了解到該頁的HTML DOM 結構,特別是你所要抓的資料是屬於那一個Table 或是那一個 id , name 之類的。這時候可以在Python 的IDLE 環境中一步一步慢慢試,不用每次執行前都要編譯,省事多了!

當使用 splinter 連上網站網頁資料時最好搭配 BeautifulSoup 4 。用起來會更方便,但遇到動態網頁時,使用 splinter 搭配JavaScript 才能針對一些AJAX 網頁及forward 網頁或openwindow 做更進一步的控制。特別是一些要輸入查詢條件及選擇日期等,有了JavaScript 的配合幾乎能克服一些難搞的狀況。等工作較不忙時,希望能整理一些心得及實例分享給大家。
     


2014/08/27

Eclipse 上安裝 Python PyDev plugin

  在Windows 上使用 Python 有兩種方式,到官方網站(http://www.python.org) 下載安裝後有兩種方式可用,一種是用命令列的方式,另一種是 IDLE 圖形介面。第二種雖然較好用但還是不理想,上網找到有一個叫 PyDev 的 plugin ,搭配 Eclipse 就好用多了。以下安裝方法提供參考:
  1. 開啟 Eclipse 3.6 以上版本,功能選單 Help > Eclipse Marketplace ...
  2. 在 Find 一欄中輸入 Python 這個字
  3. 第一個找出來的就是 PyDev - Python IDE for Eclipse, 點選右邊的 Install 鈕就對了
  4. 接下來至少要勾選 PyDev for Eclipse, 另一項用不到可以不勾, 再按 Next 下一步 , 點 I accept the terms of license agreements, 再按 Finish 
  5. 信任憑證 , 按 OK
  6. 最後安裝結束,重啟 Eclipse
  7. 接下來就可以在 Eclipse 的選單 File > New > Projects ... 看到 PyDev 的選項了,它有三個 Project 類型,分別是 PyDev Django Project / PyDev Google App Engine Project / PyDev Project 三種。 這時候還不能正常 New 專案,要先到 Windows > Preferences > PyDev > Interpreters > Python Interpreter 中, 按下右上角的 New按鈕將你已安裝的 Python.exe 路徑設定進來:
  8. 現在可以開始 New PyDev Project 在 Eclipse 中寫程式及除錯了 


2011/03/04

Python 2.6 Tk 中文亂碼問題解決方法

  在 Windows XP 想使用 Python 及 Tk 來開發圖形介面程式時針對中文字顯示都會變成亂碼,試了幾個方法後發現以下這個方法是較可行,提供給大家參考。
第一點:程式開頭一定要加底下這行編號宣告 # -*- coding:utf-8 -*- 
第二點: 字串要用在 Tk 元件上的一定要宣告成字串變數,字串中可以有許功蓋之類的字,但這些字不能在開頭及結尾 str1 = "Hello world ! 中文字成功顯示在 Tk" 
第三點: 設定 Tk 元件文字屬性時再強制設定編碼為 UTF-8 widget = Button(text=str1.encode("UTF-8"), padx=20, pady=20)
 以下是一個簡單的範例 :
# -*- coding: utf-8 -*- 
from Tkinter import * 
 class Hello(Frame): def __init__(self, parent=None): 
 Frame.__init__(self, parent) self.pack() self.make_widgets() 
 def make_widgets(self): # widget = Button(self, text=str1, command=self.quit) # 不能在 Windows 中正常顯示中文字. str1 = "Hello world ! 中文字成功顯示在 Tk" widget = Button(text=str1.encode("UTF-8"), padx=20, pady=20) widget.pack(padx=20, pady=20) widget.config(cursor='gumby') widget.config(bd=8, relief=RAISED) widget.config(bg='dark green', fg='white') widget.pack(side=LEFT) if __name__ == '__main__': Hello().mainloop()   

相同的程式在Ubuntu 11.04 Alpha 版中的 Python 2.7.1 就沒有這個問題,只要用以上第一點的編碼設定即可,不用針對中文字串再 encode .

2023/01/01 macOS 上安裝的是Python 3.9.13 沒有這個中文顯示問題。就算沒有一開始指定utf-8:

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