Silver Bullet

นั่ง​คิด​อยู่​นาน​เรื่อง​ของ​การ​ตัด​คำ​ภาษา​ไทย​ที่​น่า​จะ​มี​วิธี​ง่ายๆ ใน​ฟังก์ชั่นไม่กี่บรรทัด​ที่​ตัด​คำ​ได้​เร็ว​พอ​ควร และ​ความ​ถูก​ต้อง​ใน​ระดับ​ที่​ดู​เว็บ​แล้ว​ไม่​ปวด​หัว

ตอน​นี้​ก็​ได้​มา​อัน​นึงแล้ว

((?=[\u0e01\u0e02\u0e04\u0e07\u0e08\u0e0a\u0e0b\u0e14\u0e15\u0e16\u0e17\u0e19\u0e1a\u0e1b\u0e1c\u0e1e\u0e21\u0e22\u0e23\u0e25\u0e27\u0e2a\u0e2b\u0e2d\u0e40\u0e41\u0e42\u0e43\u0e44])(?:\u0e17(?:\u0e33(?:\u0e43\u0e2b\u0e49)?|\u0e35\u0e48|(?:\u0e32|\u0e31\u0e49)\u0e07|\u0e48\u0e32\u0e19)|\u0e40(?:\u0e23(?:\u0e37\u0e48\u0e2d\u0e07|\u0e32)|\u0e02\u0e49?\u0e32|\u0e1e(?:\u0e23\u0e32\u0e30|\u0e37\u0e48\u0e2d)|(?:[\u0e1b\u0e2b]\u0e47|\u0e0a\u0e48)\u0e19|\u0e21\u0e37\u0e48\u0e2d|\u0e01\u0e34\u0e14|\u0e14\u0e47\u0e01|\u0e27\u0e25\u0e32)|\u0e01(?:\u0e31[\u0e1a\u0e19]|\u0e32\u0e23|\u0e47|\u0e25\u0e38\u0e48\u0e21|\u0e27\u0e48\u0e32)|\u0e43(?:\u0e2b(?:\u0e49|\u0e21\u0e48)|\u0e19|\u0e0a\u0e49)|\u0e21(?:\u0e32\u0e01?|\u0e35|\u0e31\u0e19)|\u0e02(?:\u0e2d\u0e07|\u0e36\u0e49\u0e19)|\u0e08(?:[\u0e30\u0e19]|\u0e32\u0e01|(?:\u0e36|\u0e23\u0e34)\u0e07)|\u0e41(?:\u0e25(?:\u0e30|\u0e49\u0e27)|\u0e15\u0e48|\u0e2b\u0e48\u0e07|\u0e1a\u0e1a)|\u0e44(?:[\u0e14\u0e27]\u0e49|\u0e21\u0e48|\u0e1b|\u0e17\u0e22)|\u0e27(?:\u0e48\u0e32|\u0e31\u0e19)|\u0e04(?:\u0e27\u0e32\u0e21|\u0e19|\u0e37\u0e2d)|\u0e19(?:\u0e35\u0e49|\u0e31\u0e49\u0e19|\u0e32\u0e22)|\u0e2b(?:\u0e23\u0e37\u0e2d|\u0e19\u0e36\u0e48\u0e07|\u0e25\u0e32\u0e22)|\u0e2d(?:\u0e22(?:\u0e39\u0e48|\u0e48\u0e32\u0e07)|[\u0e35\u0e2d]\u0e01|\u0e32\u0e08|(?:\u0e37\u0e48|\u0e31)\u0e19|\u0e30\u0e44\u0e23)|\u0e15(?:\u0e48(?:\u0e32\u0e07|\u0e2d)|\u0e49\u0e2d\u0e07|\u0e32\u0e21|\u0e31\u0e27)|\u0e14(?:\u0e49(?:\u0e27\u0e22|\u0e32\u0e19)|\u0e35)|\u0e16(?:\u0e36\u0e07|\u0e49\u0e32|\u0e39\u0e01)|\u0e1c(?:\u0e39\u0e49|[\u0e21\u0e25])|\u0e1b(?:\u0e23\u0e30\u0e40\u0e17\u0e28|\u0e35|\u0e31\u0e0d\u0e2b\u0e32)|\u0e2a(?:\u0e31\u0e07\u0e04\u0e21|\u0e32\u0e21\u0e32\u0e23\u0e16|\u0e48\u0e27\u0e19|\u0e34\u0e48\u0e07|\u0e33\u0e04\u0e31\u0e0d)|(?:\u0e0b\u0e36\u0e48|\u0e22\u0e31|\u0e1a\u0e32|\u0e25)\u0e07|\u0e42\u0e14\u0e22|\u0e23\u0e31\u0e1a|\u0e0a\u0e35\u0e27\u0e34\u0e15|\u0e07\u0e32\u0e19|\u0e1e\u0e23\u0e23\u0e04))

เผื่อ​ใคร​งง (งง​แน่อ่ะดิ เล่น​ไม่​อธิบาย​เลย) ไอ้​ข้าง​บน​นี่​คือ Regular Expression ที่​ได้​จาก​การ Optimize 100 คำ​แรก​ที่​พบ​บ่อย​ใน​ภาษา​ไทย ทำ​ให้​สามารถ​นำ​ไป​ใช้​เป็น​ตัว​ตัด​คำ​ภาษา​ไทย​ใน​บราวเซอร์​ที่​เป็น Gecko-Based ได้ ที่​ได้​มา​นี่​เป็น​ผล​พวง​จาก​ความ​พยายาม​หา​ทาง​ที่​ง่ายๆ เอา​มา​ใช้​ใน k-meleon

Credit

สุด​ท้าย เข้า​ไป​ทด​สอบ​การ​ใช้​งาน​ได้ (ที่​นี่) ระวัง​อย่า​ใช้ IE เข้า​ไป เพราะ​มัน​จะ​ช้า​มาก

Update: เขียน​ไป​เขียน​มา ก็​ได้​เป็น Firefox Extension กัน​ไป​ใช้​งาน เท่า​ที่​ลอง​ยัง​คง​มี​บั๊ก​อยู่​เยอะ โดย​เฉพาะ​พวก Attribute ต่างๆ แต่​งาน​นี้​ก็​พอ​ใช้​งาน​ได้ (ลอง​เข้า manager แล้ว​ไม่​ระเบิด) ไว้​ว่างๆ ค่อย​มา​เขียน​ดีๆ อีก​ที

    • dogdoy
    • October 7th, 2006

    เยี่ยมเลยครับ แต่ว่าลง extension ตัวนี้ยังไงเหรอครับ ผมกด link แล้วมันก็แสดงเป็นข้อมูลออกมาเลยน่ะครับ

  1. น่าแปลกใจว่า เมื่อเปรียบเทียบระหว่างการเข้า manager กับ biolawcom นี่ biolawcom ที่เป็น text ยาวพรืดๆ กลับทำให้ fx ค้างไปสักสามถึงสี่วินาที แต่ manager แทบจะไม่ค้างเลยแฮะ

  2. silver bullet มีปัญหากับกูเกิ้ลแฮะ (มั้ง เพราะเอาออกแล้วไม่เป็น)

    ๑. หน้า login ของ Gmail ตรงปุ่ม login มันจะมี tab ขึ้นมาแบ่งทีละคำ
    ๒. กด “ค้นหา” ในกูเกิ้ลค้นหาไม่ได้!!

    ตอนนี้เจอแค่นี้นะ

    • lewcpe
    • October 7th, 2006

    dogdoy – ใช้กับ Firefox นะครับ ส่วนที่ใช้กับ k-meleon ยังทำไม่เสร็จ

    keng – เรื่องของ biolawcom นี่เหตุผลเนื่องจากความยาวรวมของ body นั้น biolawcom ยาวกว่า และมีปริมาณตัวอักษรภาษาไทยเยอะกว่า ตรงนี้น่าจะจูนให้ความเร็วดีกว่านี้ได้

    ส่วนเรื่องของกูเกิลนี่ว่าด้วยความขี้เกียจเขียนของผมล้วนๆ ครับ ไว้ทำดีๆ แล้วจะออกเวอร์ชั่นใหม่อีกรอบ

  3. แหะ ๆ เขินจังครับ เอาเวบพวกผมมาเป็นเวบทดลอง ต้องขอขอบคุณคุณ lew ครับ เพราะเป็นการโปรโมทเวบไปในตัว

    ที่ใช้กับ BioLawCom.De แล้วช้า สาเหตุหนึ่งผมคิดว่ามาจากข้อมูลที่ไม่ใช่เนื้อหาของ BioLawCom.De มีเยอะมากครับ (แต่ส่วนมากโดนซ่อนเอาไว้) ดังนั้น ผมคิดว่าหากตัดคำเฉพาะส่วนที่เป็นเนื้อหา อาจทำให้เร็วขึ้นก็ได้ครับ โดยเลือกตัดคำเฉพาะ TagId (document.getElementByID()) หรือเฉพาะ TagClass (ใช้ prototype.lite.js + document.getElementsByClassName() ) แต่วิธีนี้ทำให้คนที่ต้องการนำ script ไปใช้ต้องปรับเปลี่ยนเอกสาร HTML ก่อน ถึงจะนำไปใช้ได้

    อีกวิธีคือตัดคำฝั่ง Server ครับ โดยใช้ PHP (วิธีนี้ยิ่งเฉพาะกิจเข้าไปใหญ่) เดี๋ยวผมเอาไปลองดู ได้ผลยังไงเดี๋ยวผมจะมาเล่าให้ฟังครับ :D

  4. ไม่ค่อยรู้เรื่อง รอเวอร์ชั่นเต็ม
    แต่ดูเป็นประโยชน์มากครับ
    พี่…สุดยอด

    • lewcpe
    • October 7th, 2006

    bow_der_kleine – การตัดเฉพาะเนื้อหานี่ผมว่าค่อนข้างอันตรายครับ โดยเฉพาะในแง่ประสิทธิภาพ เข้าใจว่า Bookmarklet ของ Bact’ ก็พยายามจะตัดเฉพาะส่วนเนื้อหาที่แสดง ทำให้เมื่อเจอเว็บที่ Tag เยอะๆ แล้วบราวเซอร์เดี๊ยงไป

    ผมมองว่าเว็บที่เนื้อหาซ่อนไว้เยอะๆ คงมีไม่มากเท่าใหร่ เลยใช้วิธีตัดแหลกไว้ก่อนครับ

  5. ตอนนี้ผมลองทำให้ใช้ฝั่ง Sever ด้วย PHP ได้แล้วครับ ตอนแรกมีปัญหาอยู่บ้างตรงคำว่า “ผม”, “จาก”, “มา[\w]*”, “ว่าง” ก็เลยลองแก้ ๆ ดูครับ แก้ไปแก้มา ก็ได้ผลออกมาประมาณนี้ครับ

    function SilverBulletWrap($dataIn){
    //Thai-Wrap by LewCPE (http://lewcpe.com/blog/archives/313/silver-bullet/)
    $dataIn = preg_replace(“/(มา(?:ก|ย|ตรการ|ตรา|ตุภูมิ|ชิก))/”,”$1″,$dataIn);
    $dataIn = preg_replace(“/(ม(?:ี|ัน|ือ))/”,”$1″,$dataIn);
    $dataIn = preg_replace(“/(([กขคงจชซดตถทนบปผพมยรลวสหอเแโใไ])(?:ท(?:ำ(?:ให้)?|ี่|(?:า|ั้)ง|่าน)|เ(?:ร(?:ื่อง|า)|ข้?า|พ(?:ราะ|ื่อ)|(?:ป็|ห็|ช่)น|มื่อ|กิด|ด็ก|วลา)|ก(?:ัน|ับ|าร|็|ลุ่ม|ว่า)|ใ(?:ห(?:้|ม่)|น|ช้)|ข(?:อง|ึ้น)|จ(?:ะ|น|าก|(?:ึ|ริ)ง)|แ(?:ล(?:ะ|้ว)|ต่|ห่ง|บบ)|ไ(?:ด้|ว้|ม่|ป|ทย)|ว(?:่าง|่า|ัน)|ค(?:วาม|น|ือ)|น(?:ี้|ั้น|าย)|ห(?:รือ|นึ่ง|ลาย)|อ(?:ย(?:ู่|่าง)|[ีอ]ก|าจ|(?:ื่|ั)น|ะไร)|ต(?:่(?:าง|อ)|้อง|าม|ัว)|ด(?:้(?:วย|าน)|ี)|ถ(?:ึง|้า|ูก)|ผ(?:ู้|ม|ล)|ป(?:ระเทศ|ี|ัญหา)|ส(?:ังคม|ามารถ|่วน|ิ่ง|ำคัญ)|(?:ซึ่|ยั|บา|ล)ง|โดย|รับ|ชีวิต|งาน|พรรค))/”,”$1″,$dataIn);
    return $dataIn;
    }

    โดยผมจะใช้ฟังก์ชั่นตัดคำก่อนนำที่จะอัดข้อมูลลงฐานข้อมูล ดังนั้นตัวโปรแกรมไม่ต้องตัดคำทุกครั้งที่แสดงผลครับ ตอนจะแก้ไขข้อมูลโดยใช้ฟอร์มของ HTML ก็ต้องแก้ฟอร์แมตของข้อมูลให้เหมือนเดิมก่อนครับ โดยใช้คำสั่งง่าย ๆ คือ

    $data= str_replace(“”,”",$data);

    ดูผลงานได้ที่ (เว็บ) โป๊มะ…โป๊มั๊ยน้อง (ก็ที่เดิมนั่นแหละครับ ตัดคำแล้ว) ลองเทียบกับที่ยังไม่ตัดคำครับ (เว็บ) โป๊มะ…โป๊มั๊ยน้อง (ยังไม่ตัดคำ)

    ตอนแรกดูไม่ต่างกันมากครับ แต่ลองเพิ่มขนาดตัวอักษรดูครับ จะเห็นความแตกต่างที่ชัดเจน (เฉพาะ Firefox รุ่นไม่ตัดคำนะครับ สำหรับรุ่นตัดคำเพิ่มขนาดตัวอักษรยังไงก็เหมือนเดิม)

    • lewcpe
    • October 7th, 2006

    bow_der_kleine – ไอ้ Regex ตัวนี้มันกินเครื่องใช้ได้เลยนะครับ เอาไปใส่ฝั่งเซิร์ฟเวอร์ ระวังเดี๋ยวโฮสต์จะว่าไปทำเครื่องเค้าโหลดเอา

  6. ตัว js ดั้งเดิมที่ผมทำไว้ มันจะกรองพวกแท็กที่ไม่เกี่ยวคือ script กับ style ออกไปครับ
    สามารถเพิ่มตรงนี้ได้เหมือนกัน อาจจะทำให้เร็วขึ้นบ้าง (ลดจำนวนการเรียก regex ซึ่งเป็นตัวช้าไปได้บ้าง)
    อย่างไรก็ตาม การไล่โหนดใน DOM tree ไปเรื่อย ๆ ด้วย js
    ผมว่าประสิทธิภาพไม่น่าจะสู้การใช้ฟังก์ชั่นของ Gecko โดยตรงได้
    อันนั้นมันจะเป็นลักษณะ event-base เลย ทำงานทุกครั้งเมื่อมี event ตามที่กำหนด
    แทนที่จะวิ่งไปไล่หา event นั้นเอง
    (ผมเข้าใจว่า ตรงนี้จะช่วยลดความซ้ำซ้อนได้ เพราะยังไงตัว Gecko ก็ต้องทำตรงนี้อยู่แล้ว ไม่ว่ามี extension หรือไม่)
    เทคนิคนี้ ผมดูมาจาก extension ของคุณ vavar ในรุ่น 0.2
    Thai Words Separator extension
    https://addons.mozilla.org/firefox/2666/

    เว็บฟอนต์.คอม มีรายละเอียด/การทดสอบเรื่องนี้เยอะทีเดียว
    http://fire.f0nt.com/blog/?p=252

  7. เวรกรรม ดันไม่ทันอ่าน เข้าด้วย IE ไปแล้ว

  8. รอเสร็จครับ จะขอเอาไปใช้ทีเดียวเลย อิอิ

  1. November 10th, 2006
    Trackback from : aaa at iNfected
  2. November 10th, 2006
    Trackback from : bbb at iNfected
  3. February 6th, 2007