นั่งคิดอยู่นานเรื่องของการตัดคำภาษาไทยที่น่าจะมีวิธีง่ายๆ ในฟังก์ชั่นไม่กี่บรรทัดที่ตัดคำได้เร็วพอควร และความถูกต้องในระดับที่ดูเว็บแล้วไม่ปวดหัว
ตอนนี้ก็ได้มาอันนึงแล้ว
((?=[\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
- ฝ่ายวิจัยและพัฒนาสาขาสารสนเทศ ศูนย์เทคโนโลยีอิเล็กทรอนิกส์และคอมพิวเตอร์แห่งชาติ
- PaePae
- Bact
- Regexp::List
- บทความ จาก Biolawcom.de
สุดท้าย เข้าไปทดสอบการใช้งานได้ (ที่นี่) ระวังอย่าใช้ IE เข้าไป เพราะมันจะช้ามาก
Update: เขียนไปเขียนมา ก็ได้เป็น Firefox Extension กันไปใช้งาน เท่าที่ลองยังคงมีบั๊กอยู่เยอะ โดยเฉพาะพวก Attribute ต่างๆ แต่งานนี้ก็พอใช้งานได้ (ลองเข้า manager แล้วไม่ระเบิด) ไว้ว่างๆ ค่อยมาเขียนดีๆ อีกที
เยี่ยมเลยครับ แต่ว่าลง extension ตัวนี้ยังไงเหรอครับ ผมกด link แล้วมันก็แสดงเป็นข้อมูลออกมาเลยน่ะครับ
น่าแปลกใจว่า เมื่อเปรียบเทียบระหว่างการเข้า manager กับ biolawcom นี่ biolawcom ที่เป็น text ยาวพรืดๆ กลับทำให้ fx ค้างไปสักสามถึงสี่วินาที แต่ manager แทบจะไม่ค้างเลยแฮะ
silver bullet มีปัญหากับกูเกิ้ลแฮะ (มั้ง เพราะเอาออกแล้วไม่เป็น)
๑. หน้า login ของ Gmail ตรงปุ่ม login มันจะมี tab ขึ้นมาแบ่งทีละคำ
๒. กด “ค้นหา” ในกูเกิ้ลค้นหาไม่ได้!!
ตอนนี้เจอแค่นี้นะ
dogdoy – ใช้กับ Firefox นะครับ ส่วนที่ใช้กับ k-meleon ยังทำไม่เสร็จ
keng – เรื่องของ biolawcom นี่เหตุผลเนื่องจากความยาวรวมของ body นั้น biolawcom ยาวกว่า และมีปริมาณตัวอักษรภาษาไทยเยอะกว่า ตรงนี้น่าจะจูนให้ความเร็วดีกว่านี้ได้
ส่วนเรื่องของกูเกิลนี่ว่าด้วยความขี้เกียจเขียนของผมล้วนๆ ครับ ไว้ทำดีๆ แล้วจะออกเวอร์ชั่นใหม่อีกรอบ
แหะ ๆ เขินจังครับ เอาเวบพวกผมมาเป็นเวบทดลอง ต้องขอขอบคุณคุณ lew ครับ เพราะเป็นการโปรโมทเวบไปในตัว
ที่ใช้กับ BioLawCom.De แล้วช้า สาเหตุหนึ่งผมคิดว่ามาจากข้อมูลที่ไม่ใช่เนื้อหาของ BioLawCom.De มีเยอะมากครับ (แต่ส่วนมากโดนซ่อนเอาไว้) ดังนั้น ผมคิดว่าหากตัดคำเฉพาะส่วนที่เป็นเนื้อหา อาจทำให้เร็วขึ้นก็ได้ครับ โดยเลือกตัดคำเฉพาะ TagId (document.getElementByID()) หรือเฉพาะ TagClass (ใช้ prototype.lite.js + document.getElementsByClassName() ) แต่วิธีนี้ทำให้คนที่ต้องการนำ script ไปใช้ต้องปรับเปลี่ยนเอกสาร HTML ก่อน ถึงจะนำไปใช้ได้
อีกวิธีคือตัดคำฝั่ง Server ครับ โดยใช้ PHP (วิธีนี้ยิ่งเฉพาะกิจเข้าไปใหญ่) เดี๋ยวผมเอาไปลองดู ได้ผลยังไงเดี๋ยวผมจะมาเล่าให้ฟังครับ :D
ไม่ค่อยรู้เรื่อง รอเวอร์ชั่นเต็ม
แต่ดูเป็นประโยชน์มากครับ
พี่…สุดยอด
bow_der_kleine – การตัดเฉพาะเนื้อหานี่ผมว่าค่อนข้างอันตรายครับ โดยเฉพาะในแง่ประสิทธิภาพ เข้าใจว่า Bookmarklet ของ Bact’ ก็พยายามจะตัดเฉพาะส่วนเนื้อหาที่แสดง ทำให้เมื่อเจอเว็บที่ Tag เยอะๆ แล้วบราวเซอร์เดี๊ยงไป
ผมมองว่าเว็บที่เนื้อหาซ่อนไว้เยอะๆ คงมีไม่มากเท่าใหร่ เลยใช้วิธีตัดแหลกไว้ก่อนครับ
ตอนนี้ผมลองทำให้ใช้ฝั่ง 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 รุ่นไม่ตัดคำนะครับ สำหรับรุ่นตัดคำเพิ่มขนาดตัวอักษรยังไงก็เหมือนเดิม)
bow_der_kleine – ไอ้ Regex ตัวนี้มันกินเครื่องใช้ได้เลยนะครับ เอาไปใส่ฝั่งเซิร์ฟเวอร์ ระวังเดี๋ยวโฮสต์จะว่าไปทำเครื่องเค้าโหลดเอา
ตัว 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
เวรกรรม ดันไม่ทันอ่าน เข้าด้วย IE ไปแล้ว
รอเสร็จครับ จะขอเอาไปใช้ทีเดียวเลย อิอิ