วันพุธที่ 19 ตุลาคม พ.ศ. 2554

Php + Autoit3 ดึงข้อมูลจากหน้า Website ทั่วไป ไปเก็บลงใน Database

1. โหลด Autoit3 ก่อนที่ http://www.autoitscript.com/site/autoit/downloads/

2. เขียน Script ให้โหลดข้อมูลจากหน้า Web

 เปิดเว็บสำรวจก่อนทำ     เมื่อจะเริ่มเขียนโปรแกรมที่เกี่ยวข้องกับเว็บหรืออะไรอื่น ก็ต้องทำความเข้าใจในสิ่งที่เราจะเขียนเสียก่อน ลองเปิดเว็บ http://th.wikipedia.org ขึ้นมาดู ข้อความที่เราจะดึงออกมาคือคอลัมน์ คำที่เขียนถูก และ มักเขียนผิดเป็น


     พอเลื่อนลงมาอีกหน่อยก็พบว่าคำเรียงตามตัวอักษร และมีการสร้างตารางใหม่ตามอักษรแต่ละตัวโดยใช้แท็ก Table (ภาษา HTML ในการเขียนเว็บ)จุดประสงค์ในการเขียนสคริปต์ของผมคือ ต้องการแค่ดึงเอาข้อความเขียนถูกและมักเขียนผิดมาเรียงต่อกันเท่านั้น โดยไม่เอาตารางมาด้วย การที่ตารางในเว็บแยกตามตัวอักษรจะทำให้มีข้อความ คำที่เขียนถูก มักเขียนผิดเป็น ปรากฏขึ้นมาเวลาใช้คำสั่งดึงข้อมูลออกมาด้วย  ปัญหาต่างๆ เหล่านี้สามารถแก้ไขได้ด้วยการเขียนสคริปต์ตามตัวอย่างในหัวข้อถัดไป


เริ่มเขียนสคริปต์ AutoIt ดึงข้อมูลจากเว็บ
    เริ่มแรกก็เขียนสคริปต์เปิดหน้าเว็บ ด้วยความที่ URL ค่อนข้างยาวผมจะใช้ตัว  & _ (Line Continuation) ในการเชื่อม URL ที่แยกไปแต่ละบรรทัด

#include <IE.au3>
$oIE = _IECreate ("http://th.wikipedia.org/wiki/"
& _
"%E0%B8%A3%E0%B8%B2%E0%B8%A2%E0%B8%" & _
"8A%E0%B8%B7%E0%B9%88%E0%B8%AD" & _
"%E0%B8%84%E0%B8%B3%E0%B9%83%E0%B8%" & _
"99%E0%B8%A0%E0%B8%B2%E0%B8%A9%E0" & _
"%B8%B2%E0%B9%84%E0%B8%97%E0%B8%A2%" & _
"E0%B8%97%E0%B8%B5%E0%B9%88%E0%B8%A1%E0%B8" & _
"%B1%E0%B8%81%E0%B9%80%E0%B8%82%E0%B8%B5%" & _
"E0%B8%A2%E0%B8%99%E0%B8%9C%E0%B8%B4%E0%B8%94")

ตอนนี้ก็ได้สคริปต์เปิดหน้าเว็บมาแล้ว จากนั้นก็เขียนสคริปต์ต่อเพื่อตรวจดูว่าในเว็บมีตารางจำนวนกี่ตารางกันแน่ สรุปแล้วในหน้าเว็บมีตาราง 41 อัน (เริ่มต้นที่ 0)

#include <IE.au3>
$oIE = _IECreate ("http://th.wikipedia.org/wiki/" & _
"%E0%B8%A3%E0%B8%B2%E0%B8%A2%E0%B8%" & _
"8A%E0%B8%B7%E0%B9%88%E0%B8%AD" & _
"%E0%B8%84%E0%B8%B3%E0%B9%83%E0%B8%" & _
"99%E0%B8%A0%E0%B8%B2%E0%B8%A9%E0" & _
"%B8%B2%E0%B9%84%E0%B8%97%E0%B8%A2%" & _
"E0%B8%97%E0%B8%B5%E0%B9%88%E0%B8%A1%E0%B8" & _
"%B1%E0%B8%81%E0%B9%80%E0%B8%82%E0%B8%B5%" & _
"E0%B8%A2%E0%B8%99%E0%B8%9C%E0%B8%B4%E0%B8%94")

  $oTable = _IETableGetCollection ($oIE)
  $iNumTables = @extended
MsgBox(0, "Table Info", "There are " & $iNumTables & " tables on the page")


     ลองใช้คำสั่งดึงเอาตารางแต่ละอันมาดู และเนื่องจากคำสั่ง _IETableGetCollection  จะดึงเอาข้อมูลไปเก็บไว้ในอาเรย์อัตโนมัติ จึงต้องเพิ่มคำสั่ง #include <Array.au3> เข้ามาด้วย เพื่อใช้คำสั่ง  _ArrayDisplay ในการแสดงข้อมูลในอาเรย์ จากนั้นก็ไล่ดูทีละตารางว่ามีข้อมูลอะไรอยู่


#include <IE.au3>
#include <Array.au3>
$oIE = _IECreate ("http://th.wikipedia.org/wiki/" & _
"%E0%B8%A3%E0%B8%B2%E0%B8%A2%E0%B8%" & _
"8A%E0%B8%B7%E0%B9%88%E0%B8%AD" & _
"%E0%B8%84%E0%B8%B3%E0%B9%83%E0%B8%" & _
"99%E0%B8%A0%E0%B8%B2%E0%B8%A9%E0" & _
"%B8%B2%E0%B9%84%E0%B8%97%E0%B8%A2%" & _
"E0%B8%97%E0%B8%B5%E0%B9%88%E0%B8%A1%E0%B8" & _
"%B1%E0%B8%81%E0%B9%80%E0%B8%82%E0%B8%B5%" & _
"E0%B8%A2%E0%B8%99%E0%B8%9C%E0%B8%B4%E0%B8%94")

  $oTable = _IETableGetCollection ($oIE,1)
    $aTable = _IETableWriteToArray ($oTable, True)
    _ArrayDisplay(  $aTable)


   ไล่ดูแล้วปรากฏว่าตารางแรกไม่ต้องดึงออกมา และตารางสุดท้ายก็ไม่จำเป็น สรุปแล้วเราจะดึงเอาข้อมูลจากตาราง 1 ถึง 39 เท่านั้น ทดลองเขียนคำสั่งดึงเอาตาราง 1 ถึง 39 ออกมาได้ดังนี้

#include <IE.au3>
#include <Array.au3>
$oIE = _IECreate("http://th.wikipedia.org/wiki/" & _
        "%E0%B8%A3%E0%B8%B2%E0%B8%A2%E0%B8%" & _
        "8A%E0%B8%B7%E0%B9%88%E0%B8%AD" & _
        "%E0%B8%84%E0%B8%B3%E0%B9%83%E0%B8%" & _
        "99%E0%B8%A0%E0%B8%B2%E0%B8%A9%E0" & _
        "%B8%B2%E0%B9%84%E0%B8%97%E0%B8%A2%" & _
        "E0%B8%97%E0%B8%B5%E0%B9%88%E0%B8%A1%E0%B8" & _
        "%B1%E0%B8%81%E0%B9%80%E0%B8%82%E0%B8%B5%" & _
        "E0%B8%A2%E0%B8%99%E0%B8%9C%E0%B8%B4%E0%B8%94")

For $i = 1 To 39
    $oTable = _IETableGetCollection($oIE, $i)
    $aTable = _IETableWriteToArray($oTable, True)
    _ArrayDisplay($aTable)
Next


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



#include <IE.au3>
#include <Array.au3>
$oIE = _IECreate("http://th.wikipedia.org/wiki/" & _
        "%E0%B8%A3%E0%B8%B2%E0%B8%A2%E0%B8%" & _
        "8A%E0%B8%B7%E0%B9%88%E0%B8%AD" & _
        "%E0%B8%84%E0%B8%B3%E0%B9%83%E0%B8%" & _
        "99%E0%B8%A0%E0%B8%B2%E0%B8%A9%E0" & _
        "%B8%B2%E0%B9%84%E0%B8%97%E0%B8%A2%" & _
        "E0%B8%97%E0%B8%B5%E0%B9%88%E0%B8%A1%E0%B8" & _
        "%B1%E0%B8%81%E0%B9%80%E0%B8%82%E0%B8%B5%" & _
        "E0%B8%A2%E0%B8%99%E0%B8%9C%E0%B8%B4%E0%B8%94")

For $i = 1 To 39
    $oTable = _IETableGetCollection($oIE, $i)
    $aTable = _IETableWriteToArray($oTable, True)
    _ArrayDelete($aTable, 0)
    _ArrayDisplay($aTable)
Next


     ปัญหาถัดมาคือคอลัมน์ที่ 3 ซึ่งเป็นคอลัมน์ที่แสดง หมายเหตุ วิธีการแก้ไขปัญหาตรงนี้ก็ง่ายๆ เลยคือ สร้างตัวแปรแบบอาเรย์ที่เก็บค่าได้แค่ 2 คอลัมน์ โดยใช้คำสั่ง Dim $tb[1][2] เพื่อนำเอาข้อมูลคอลัมน์แรกและคอลัมน์ที่สองใส่ไปเท่านั้น ปัญหาสุดท้ายก็คือเราจะเอาตารางทั้งหมดมารวมกันเป็นตารางเดียวได้อย่างไร วิธีแก้ไขปัญหาก็อาศัยตัวแปรแบบอาเรย์ที่เราสร้างขึ้นมานั่นเอง โดยเอาค่าตารางที่ได้แต่ละอันจับมาใส่ในตัวแปรแบบอาเรย์นั้นครับ เพื่อให้เข้าใจยิ่งขึ้นต้องเขียนโค้ดแยกออกมาต่างหาก จะได้ดังนี้

For $i = 0 To UBound($aTable) - 1
        ReDim $tb[UBound($tb) + 1][2]
        $tb[UBound($tb, 1) - 1][0] = $aTable[$i][0]
        $tb[UBound($tb, 1) - 1][1] = $aTable[$i][1]
    Next


     ผมจะใช้คำสั่ง for ในการวนลูป แต่จำนวนการวนแต่ละลูปจะไม่เท่ากันเพราะจะอ้างอิงขนาดข้อมูลในตารางจึงต้องใช้คำสั่ง UBound มานับข้อมูลในตาราง แต่จะติดปัญหานิดหนึ่งคือมันจะข้อมูลเป็นจำนวนไม่ใช่แถวที่อ้างอิงในอาเรย์ดังนั้นต้องใส่ –1 ต่อลงไป เพราะแถวข้อมูลในอาเรย์จะเริ่มต้นที่แถว 0 นั่นเอง

เสร็จแล้วก็เปลี่ยนขนาดของอาเรย์เดิมโดยใช้คำสั่ง ReDim คือ
    ReDim $tb[UBound($tb) + 1][2]

เพื่อปรับขนาดของอาเรย์ให้เท่ากับจำนวนข้อมูลในตาราง หลักการคือบวกเพิ่มแถวเก็บข้อมูลอาเรย์ทุกครั้งที่มีการวนลูป อีกสองแถวถัดมาคือ

        $tb[UBound($tb, 1) - 1][0] = $aTable[$i][0]
        $tb[UBound($tb, 1) - 1][1] = $aTable[$i][1] 


     จะเป็นการดึงเอาข้อมูลในตัวอาเรย์เดิมมาจับใส่ในในอาเรย์ที่เพิ่งปรับขนาด และจะเกิดปัญหาอีกอย่างหนึ่งขึ้นมาอีกคือ ในการใส่คำสั่ง For ซ้อนเข้าไปใน For เดิม การวนลูปตารางในตัวอักษรถัดไป จะทำให้เกิดการล้างข้อมูลเดิมทิ้ง ดังนั้นจึงจำเป็นต้องเขียนแยกออกเป็นฟังก์ชัน โดยขนเอาข้อมูลอาเรย์ในลูป For ที่อยู่ในคำสั่งแรกออกไปใส่ วิธีประกาศฟังก์ชันตามปกติข้อมูลจะถูกล้างเหมือนเดิม เราจะใช้เทคนิคอยู่อย่างหนึ่งก็คือ ใช้คำสั่ง ByRef ควบคุมตัวแปร $tb เพื่อให้มันเก็บข้อมูลเดิมเอาไว้เสมอเมื่อมีการเพิ่มข้อมูลใหม่เข้ามา วิธีเขียนส่งตัวแปรเข้าไปในฟังก์ชันก็เขียนดังนี้

tbsum($tb, $aTable) ส่วนหัวฟังก์ชันก็จะได้ดังนี้ (ชื่อตัวแปรไม่จำเป็นต้องเขียนเหมือนตัวแปรที่ส่งเข้าไป แต่เพื่อให้เข้าใจง่ายผมจะเขียนชื่อเหมือนเดิม)

Func tbsum(ByRef $tb,$aTable)

เมื่อนำมาแก้ไขก็จะได้ดังนี้ (ลองเอาไปรันดู)

#include <IE.au3>
#include <Array.au3>
$oIE = _IECreate("http://th.wikipedia.org/wiki/" & _
        "%E0%B8%A3%E0%B8%B2%E0%B8%A2%E0%B8%" & _
        "8A%E0%B8%B7%E0%B9%88%E0%B8%AD" & _
        "%E0%B8%84%E0%B8%B3%E0%B9%83%E0%B8%" & _
        "99%E0%B8%A0%E0%B8%B2%E0%B8%A9%E0" & _
        "%B8%B2%E0%B9%84%E0%B8%97%E0%B8%A2%" & _
        "E0%B8%97%E0%B8%B5%E0%B9%88%E0%B8%A1%E0%B8" & _
        "%B1%E0%B8%81%E0%B9%80%E0%B8%82%E0%B8%B5%" & _
        "E0%B8%A2%E0%B8%99%E0%B8%9C%E0%B8%B4%E0%B8%94")

Dim $tb[1][2]
For $i = 1 To 39
    $oTable = _IETableGetCollection($oIE, $i)
    $aTable = _IETableWriteToArray($oTable, True)
    _ArrayDelete($aTable, 0)
    tbsum($tb, $aTable)
Next

    _ArrayDelete($aTable, 0)
_ArrayDisplay($tb)
Func tbsum(ByRef $tb,$aTable)
    For $i = 0 To UBound($aTable) - 1
        ReDim $tb[UBound($tb) + 1][2]
        $tb[UBound($tb, 1) - 1][0] = $aTable[$i][0]
        $tb[UBound($tb, 1) - 1][1] = $aTable[$i][1]
    Next
EndFunc


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

 $file = FileOpen("test.txt", 2)


For $i = 0 To UBound($tb) - 1
FileWriteLine($file, "ลำดับที่:"&$i+1&$tb[$i][1]&" คำที่เขียนถูกคือ "&$tb[$i][0] & @CRLF)
Next


FileClose($file)
Run("notepad.exe test.txt")

สคริปต์โปรแกรมเมื่อทำเสร็จสิ้นแล้วก็จะได้ดังตัวอย่างนี้ด้านล่างนี้ครับ



#include <IE.au3>
#include <Array.au3>


$oIE = _IECreate("http://th.wikipedia.org/wiki/" & _
        "%E0%B8%A3%E0%B8%B2%E0%B8%A2%E0%B8%" & _
        "8A%E0%B8%B7%E0%B9%88%E0%B8%AD" & _
        "%E0%B8%84%E0%B8%B3%E0%B9%83%E0%B8%" & _
        "99%E0%B8%A0%E0%B8%B2%E0%B8%A9%E0" & _
        "%B8%B2%E0%B9%84%E0%B8%97%E0%B8%A2%" & _
        "E0%B8%97%E0%B8%B5%E0%B9%88%E0%B8%A1%E0%B8" & _
        "%B1%E0%B8%81%E0%B9%80%E0%B8%82%E0%B8%B5%" & _
        "E0%B8%A2%E0%B8%99%E0%B8%9C%E0%B8%B4%E0%B8%94")

Dim $tb[1][2]
For $i = 1 To 39
    $oTable = _IETableGetCollection($oIE, $i)
    $aTable = _IETableWriteToArray($oTable, True)
    _ArrayDelete($aTable, 0)
    tbsum($tb, $aTable)
Next
_ArrayDelete($tb, 0)

$file = FileOpen("test.txt", 2)
For $i = 0 To UBound($tb) - 1
FileWriteLine($file, "ลำดับที่:"&$i+1&$tb[$i][1]&" คำที่เขียนถูกคือ  "&$tb[$i][0] & @CRLF)
Next
FileClose($file)
Run("notepad.exe test.txt")

Func tbsum(ByRef $tb, $aTable)
    For $i = 0 To UBound($aTable) - 1
        ReDim $tb[UBound($tb) + 1][2]
        $tb[UBound($tb, 1) - 1][0] = $aTable[$i][0]
        $tb[UBound($tb, 1) - 1][1] = $aTable[$i][1]
    Next
EndFunc


// ไฟล์ที่ใช้งานจริง

#include <IE.au3>
#include <Array.au3>

$oIE = _IECreate("c:\wlevel.htm")
Dim $tb[1][2]
For $i = 1 To 4
    $oTable = _IETableGetCollection($oIE, $i)
    $aTable = _IETableWriteToArray($oTable, True)
    _ArrayDelete($aTable, 0)
    tbsum($tb, $aTable)
Next
_ArrayDelete($tb, 0)
$file = FileOpen("test.txt", 2)
For $i = 0 To UBound($tb) - 1
FileWriteLine($file, &$tb[$i][1] @CRLF)
Next
FileClose($file)
_IEQuit($oIE)
Func tbsum(ByRef $tb, $aTable)
    For $i = 0 To UBound($aTable) - 1
        ReDim $tb[UBound($tb) + 1][2]
        $tb[UBound($tb, 1) - 1][0] = $aTable[$i][0]
  $tb[UBound($tb, 1) - 1][1] = $aTable[$i][1]
     
    Next
EndFunc



** เสร็จแล้ว Compile ให้เป็น exe file
ทดลอง Run ดูจะได้ text file ผลลัพธ์ดังนี้


3. สร้างไฟล์ PHP สำหรับดึงข้อมูลไปใช้งาน
<?php
$cmd = 'C:\AppServ\www\sk_forebay\headlevel.exe'; //บอกที่อยู่ไฟล์ exe ที่ comfile จาก autoit
exec($cmd); //run file ที่ comfile จาก autoit
// ข้อมูลที่ได้จากการใช้ Function file() จะได้ออกมาเป็น Array แต่ละบัีนทัดข้อมูลที่เก็บใน File คือ 1 ค่า index ของ Array
$data=file("C:/AppServ/www/sk_forebay/test.txt"); 
//for($i=0;$i<count($data);$i++){  // วนรอบเพื่อแสดงผลขอ้มูล
//echo $data[1]."<br>";
//}
//แยกวัน-เวลา
 $myhead = substr($data[0],0,6);
 $myyear = substr($data[1],0,4);
 $mymonth = substr($data[1],4,2);
 $mydate = substr($data[1],6,2);
 $myhour = substr($data[1],9,2);
 $myminute = substr($data[1],11,2);
  $mysec = substr($data[1],13,2);
  $mydate =  $myyear."-".$mymonth."-".$mydate." ".$myhour.":".$myminute.":".$mysec;
  echo "วันเวลา = ".$mydate." ข้อมูลระดับน้ำ  = ".$myhead." เมตร รทก.";
?>

............................. function _IETagnameGetCollection------

#include <IE.au3>

$oIE = _IECreate("http://www.facebook.com")
_IELoadWait($oIE)
$oDiv = _IEGetObjById($oIE, 'contentArea')
$oLinks = _IETagnameGetCollection($oDiv, "span");ถ้าไม่ได้ลองเปลี่ยนจาก span เป็น div หรือ button
For $oLink In $oLinks
$text = $oLink.innerText
If StringInStr($Text, "ถูกใจ") Then
_IEAction($oLink, "click")
MsgBox(0,"คลิกถูกใจ",$text )
Sleep(100)
EndIf
Next


----


$oInputs = _IETagNameGetCollection($oIE, "input"); Input Fields For $oInput In $oInputs     If $oInput.name = "RITD_NAME" Then $oInput.Value = "COMPANY NAME - PolType"     If $oInput.name = "CONTENT.POLEFFDATEmin"  Then $oInput.Value = "01/01/2003"     If $oInput.name = "CONTENT.POLEFFDATEmax"  Then $oInput.Value = "01/01/2008"     If $oInput.name = "RITD_NOTIFYIND" Then $oInput.Checked = False     If $oInput.name = "CONTENT.GP_FINANCIAL_SLRmin" Then $oInput.Value = "1"     If $oInput.name = "OPTIONS.RPTTITLE" Then $oInput.Value = "COMPANY NAME"     If $oInput.name = "OPTIONS.TXTTRLR" Then $oInput.Checked = False Next


--


$oInputs = _IETagNameGetCollection($oIE, "span") ; @extended would be 38 at this point     For $oInput in $oInputs         If $oInput.id = 0 Then             $oInput.Click; Clicks the first 'span' then exits the For loop             ExitLoop         EndIf     Next


If String(_IEPropertyGet($oInput, "innerText")) = "Submit" Then

ตัวอย่างทำสั่งทั้งหมดของ autoit
http://www.autoitscript.com/autoit3/docs/libfunctions/

ไม่มีความคิดเห็น:

แสดงความคิดเห็น