Wednesday, March 31, 2010

Web Parser

以前沒寫過,也沒去想過一個撈資料的工具該怎麼運作。這兩天閒著(其實已經閒了快一個月惹=    = ),不如花點時間研究一下,也找到一個算是有用的輔助工具,分享一下。
> HTML Agility Pack:簡單好用的快速 HTML Parser

開始前稍微瞭解了一下最基本的原理。
  1. 跟我猜想的一樣,利用HTML tag。 如果網頁寫的好、夠結構化,那撈資料的作業也比較好進行。遺憾的是,HTML就是可以不嚴謹,標籤不一定成對,只能祈求還能從中找到一些規律了XD
  2. 第1點用的是比字串的方法,據說效能不好(因為還沒大量撈資料,我實在感覺不出來=   =)。另一個方法是利用Regular Expression。 但是這對剛入門的人來說實在是... 門檻相當高,想要寫出一個可用的regular expression,還必須先好好了解每個符號的意義。而且就我這次的經驗(撈一層包一層的HTML tags),似乎派不上用場。
第一次寫web parser,對像是PTT WebBBS,他單篇文章的HTML架構還滿簡潔的,簡單到... 反而讓人困擾XDD,要將表頭(作者、標題、時間)、內文、推文分開還比較難,因為他們全部放在一組div裡,就沒其他tag了XDD。

文章列表就比較有挑戰性一點,不過這個挑戰用上面推薦的HTML Agility Pack就搞定了XD

因為parser這東西是針對不同網站,解析的寫法就完全不同,應該說是完全客製化了吧,所以,就不介紹code的部分了~ 沒事可以玩玩,還滿有趣的 =D
Wednesday, March 24, 2010

[Study] Oracle Extended ROWID & Base-64 Decode

最近讀到ROWID這東西… 費了我不少時間啊 orz。

Introduction
ROWID顧名思義,可以透過他來識別/定位資料庫裡的任何一個row。他並非真正的欄位(column),但是在每個表(table)裡,我們都可以下select ROWID來取得他的值。

Format
先簡單介紹一下Extended ROWID的構成 (在Oracle7以及更早以前的版本是所謂的Restricted ROWID,這裡不討論),ROWID是經過base-64編碼後以18個字元呈現,需用到最大10 byte的儲存空間。


  • Data object #: 6個字元。白話一點說,就是row所在的table。以oracle的邏輯架構來看,table算是一個segment,而透過segment我們可以知道這個row在哪個Tablespace內
  • Relative file #: 3個字元。定位row實際上是在哪個datafile內
  • Block #: 6個字元。定位row所在的data block
  • Row #: 3個字元。定位row本身

ROWID
SQL> select rowed from hr.jobs where job_id='XXX';

實際上select出的ROWID,大概是長這樣 → AAAgwuAAKAAAl7hAAR
拆解各部份套到上面圖示,會是這樣:


原本以為到DBA_OBJECTS內找到相對應的'DATA_OBJECT_ID'欄位也會是"AAAgwu",結果大錯特錯。

SQL> select data_object_id from dba.objects where owner='HR' and object_name='JOBS';

得到的值竟然是一個數字!!! "134190"!!!! what!?!?
嗯… 因為我上面有提到,ROWID的18個字元,是經過base-64編碼的… 必須再處理過,才會是134190這個data object number。

BASE64 to Decimal
其實sys下也有現成的package可用: DBMS_ROWID (This package provides procedures to create ROWIDs and to interpret their contents),只要把rowid丟進DBMS_ROWID.ROWID_INFO內(外加其他幾個承接結果的變數),就可以得到每一段轉換過後的數字。詳細用法可參考這兒

可以得到現成的結果還不錯,不過還是想知道他事實上到底是怎麼換算的,在找了幾篇失敗的解說後,找到了這篇!! 透過他提供的SQL, 就可以了解其中過程。


Create Or Replace Package B64 Is
B64 Varchar2(64):='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
Function Base64_2Dec(Val Varchar2) Return Number;
Function Dec2_Base64(Val Number) Return Varchar2;
End B64;
/
Create Or Replace Package Body B64 Is
Function Base64_2Dec
(Val Varchar2)
Return Number Is
I Pls_Integer;
J Pls_Integer;
K Pls_Integer:=0;
N Pls_Integer;
V_Out Number(38):=0;
Begin
  N:=Length(B64);
  For I In Reverse 1..Length(Val) Loop
    J:=Instr(B64,Substr(Val,I,1))-1;
    If J <0 Then
      Raise_Application_Error(-20001,'Invalid Base 64 Number: '||Val);
    End If;
    V_Out:=V_Out+J*(N**K);
    K:=K+1;
  End Loop;
  Return V_Out;
End;

Function Dec2_Base64
(Val Number)
Return Varchar2 Is
V_In Number;
N Pls_Integer;
V_Out Varchar2(30):='';
Begin
  N:=Length(B64);
  V_In:=Trunc(Val);
  While (V_In>0) Loop
    V_Out:=Substr(B64,Mod(V_In,N)+1,1)||V_Out;
    V_In:=Trunc(V_In/N);
  End Loop;
  Return V_Out;
End;

End B64;
/

(有點懶得解釋= = 請自行閱讀,B64那串字就是base-64的64個字元,請看Ref #3)

所以當我下
SQL> select rowid ,
B64.Base64_2Dec(substr(rowid,1,6)) object_no ,
B64.Base64_2Dec(substr(rowid,7,3)) rel_file_id,
B64.Base64_2Dec(substr(rowid,10,6)) block_no,
B64.BASE64_2DEC(SUBSTR(ROWID,16,3)) ROW_NO
from hr.jobs where job_id='XXX';

可以得到
ROWID                          OBJECT_NO REL_FILE_ID   BLOCK_NO    ROW_NO
------------------                     ----------------     ----------------      --------------       -------------
AAAgwuAAKAAAl7hAAR       134190                10           155361               17


完畢!!

Ref:
  1. 如何使用base64编码解构Oracle rowid信息
  2. Oracle DBMS_ROWID
  3. Base64
Monday, March 22, 2010

[Study] Unicode、Encoding(編碼)


前幾天有篇文章忽然出現在河道上浮浮載載,又身為被點名的「軟體開發者(Software Developer)」,於是相當認真的看了一下… 相當慚愧的,我還是不懂orz

文章在這:

中文版: 每個軟體開發者都絕對一定要會的Unicode及字元集必備知識(沒有藉口!)

英文版: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)


我覺得可能是因為本身對整個編碼的基礎知識相當薄弱,所以造成對內文的理解與接受度也大幅度降低惹... Q口Q,既然是欠缺基礎,還是做點筆記吧… 不過我後來有注意到其實這篇文章已經有點年紀了… 所以不太確定他的內容或是他所提供的參考資料是否還跟的上事實。


Code pages、字元集(character set)、encodings
編碼系統0-127128-255system
ASCII0-31: 控制字元

32-127: 數字、英文字母大小寫、常用符號
未定義使用
ANSI同ASCII似ISO Latin-1Windows 3.x

Windows 95
IBM PC Extended Character Set (ECS)同ASCII定義歐洲字元(European characters)DOS
Roman-8
European characters
HP
ISO Latin-1Web browsers


Unicode
Unicode(統一碼、萬國碼、單一碼、標準萬國碼)是業界的一種標準,它可以使電腦得以呈現世界上數十種文字的系統。在文字處理方面,Unicode的功用是為每一個字元提供一個唯一的代碼(Code Point, 即一組數字),而不是一種字形。換句話說,Unicode是將字元以一種抽象的方式來呈現,而將視覺上的演繹工作(例如字體大小、外觀形狀、字體形態、文體等)留給其他軟體來處理,例如網頁瀏覽器或是文字處理器。


Encodings (編碼)

方法一:UCS-2(UTF-16)
每個字元(的代碼, code point)佔用2個byte(也就是16 bit),所以理論上最多可以以16 bit去定義出65,536個字元(216)。但事實上unicode並為用滿整個16 bit,所以還有擴展空間。而UCS-2又分為high-endian(Big-Endian, 大端序)與low-endian(Little-Endian, 小端序)兩種讀取順序/模式,因為不同機器(CPU)對byte會有不同的理解順序。

方法二:UTF-8
因為UCS-2的編碼方式會造成基本英文字母浪費了相當多的bit空間,於是發展出UTF-8。在UTF-8的系統裡,0-127的基本符號、英數字母都只佔一個byte,128以上的字元則不一定,大部分佔2-3 byte,最多甚至可到6 byte。

補充:
根據wiki上的說法,其實編碼方式跟實現方式是兩回事:上面提到的UCS-2是編碼方式,而Unicode的實現方式稱為Unicode轉換格式(Unicode Translation Format,簡稱為UTF)。

還有許多其他編碼方式都只能正確儲存部分代碼(code points), 其餘他們不認得的編碼會變成問號(?)。通常UTF-7, 8, 16, 32可以正確儲存所有的代碼(code points)。


以上!! 吸收完畢!! 希望是對的=_______=。


Ref:

  1. ASCII Characters for MPE Users
  2. Windows Uses the ANSI Character Set
  3. IBM PC Extended Character Set (ECS)
  4. European Characters in Web Pages
  5. Roman-8 European Characters (HP)
  6. [wiki] Code Page
  7. [wiki] Unicode(中) or [wiki] Unicode
  8. [wiki] Character encoding
Friday, March 19, 2010

Blogger: 在新視窗開啟連結

媽啊!! 終於成功惹!!!

先留個資料,改天再補!!


 

Ref:

  1. Blogger/Blogspot: open all links in new windows
  2. "Better" Standards-based Replacement for target="_blank" in External Links
  3. Standards-based Replacement for target="_blank" in External Links
Tuesday, March 16, 2010

SQL Developer 2.1.1: Font of Code Editor and Data Grids

昨天上oracle去晃晃,忽然發現SQL Developer又有新版本惹~ 二月就出了2.1的patch 1,我整個大delay啊orz.. 所以趕快就抓了新的下來用。

來說說使用半個小時後的感想:

最令人驚艷的是開啟時的速度,效能大增啊!!! 所以還在1.5.5的人相當建議快快更新你的SQL Developer版本~

不過有一點比較不習慣的是,因為年紀有點大XD,我習慣把Code Editor的字型放大,但是這個改變也會一起動到輸出的結果(Script Output Window)與所有資料表檢視(Data Grids)… 可是我並不想看到這麼大字的輸出或是資料表啊Q_Q整個很笨拙的感覺,不過找了一下資料,看來是暫時無法改變這件事情惹..

Ref:

  1. [Sue's Blog… again…] Back to Basics: Changing the Font Setting in SQL Developer
  2. [OTN] Oracle SQL Developer Release 2.1 Patch 1 Release Notes

Monday, March 15, 2010

SQL Developer problem: 某些按鍵(key/button)無作用(not working)

上禮拜在用sql developer的時候,也不知道手滑去按到什麼鍵,他忽然就不接受鍵盤的某些按鍵了!! 像是backspace, delete, ctrl+v等的… 原本以為可能作業系統忽然秀逗了還怎樣,應該重開機就好了(重開機是一切啊~ = =)

不過相當遺憾的,還是失敗了。不過解法相當簡單:

中文版(版本: 1.5.5)
工具> 偏好設定> 快速鍵> 載入預先設定> 選擇Default> 確定

英文版(version: 1.5.5)
Tools -> Preferences -> Accelerators -> Load Preset -> Default -> OK

相當簡單就不附圖了!! 希望有幫助~

Ref:

Oracle SQL Developer problem – backspace / delete button not working – quick fix

Tags