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

Friday, March 12, 2010

Length Semantics for Character Datatypes

How to determine the column length in different database character set and length semantics? For example, you need to define a VARCHAR2 column that can store up to 5 Chinese characters together with 5 English characters.

Database Character Set

Length Semantics

Single byte

Multiple byte

BYTE

10 BYTE

5*3+5*1=20 BYTE

CHAR

10 CHAR

10 CHAR

Tags