Python 2 Module Mechanize :: ย้ายมาจาก Blog เดิมเมื่อหลายปีก่อน

เนื่องจากผมเขียน script ภาษา Python มาระยะนึงแล้วติดเรื่องของการใช้งานเกี่ยวกับ HTTP ผมไปเจอ module นึงน่าสนใจมาก ๆ และมี refer link สำหรับช่วยในการใช้งาน module นั่นคือ Mechanize ซึ่งจะคอยอำนวยความสะดวกในการสร้าง Object ประเภท web browser ได้ผมเลยลองศึกษาและเขียน script ขึ้นมาใช้งานเฉพาะทาง ^^ ขอไม่เอ่ยถึงนะครับ ก็ผิดพลาดเกี่ยวกับตัว version ของ Python เหมือนกันเพราะว่า Mechanize นั้นรองรับเฉพาะ Python 2 เท่านั้นไม่รองรับ Python 3 แต่ก็มีผู้ใจดีสร้าง Module เรียนแบบ Mechanize ขึ้นมาโดยใช้การผสมผสานของ Module ชื่อดังสองเจ้าคือ BeautifulSoup และ Requests โดยตั้งชื่อไว้ว่า MechanicalSoup นั่นเอง หากใครใช้ Python 3 ก็แนะนำให้ใช้ MechanicalSoup แทนนะครับ หรือจะใช้ BeautifulSoup 4 กับ Requests ก็ได้ครับ แต่ต้องไปศึกษาเพิ่มเติมนิดหน่อย


มาเข้าเรื่องกันดีกว่าสำหรับเจ้า Mechanize นั้นเป็น module สำหรับสร้าง Object ประเภท web browser เพื่อใช้ในการทำงานร่วมกับ website นั่นเอง โดยที่เราจะต้องติดตั้ง module ดังกล่าวลงไปที่เครื่องของเราเสียก่อน โดยเปิด terminal ขึ้นมาครับ ถ้าใช้ windows ก็เปิด cmd.exe ขึ้นมา แล้วพิมพ์คำสั่ง

1
pip install mechanize

แล้วกดปุ่ม Enter ได้เลยครับ รอมันทำงานก่อน หลังจากที่ติดตั้งเสร็จแล้วก็มาเริ่มเขียน code กันเลย เปิดโปรแกรม text editor ขึ้นมาครับ ใครถนัดตัวไหนก็ใช้ตัวนั้นครับ ส่วนตัวผมถนัดใช้ sublime text 3 ครับ บรรทัดแรกใส่ shebang ลงไปเสมอ เพื่อให้สามารถรันได้ทั้ง windows และ Unix Base (Linux, Mac OS) คือถ้าไม่ใส่อาจจะใช้ได้เฉพาะบน windows นะครับ หากใครไม่รู้จักหัวข้อถัดไปเลยครับ

Shebang คืออะไร
Shebang ก็คือบรรทัดแรกของ script ที่จะบ่งบอกถึงตัว compiler ที่จะใช้ในการประมวลผล script file ที่ท่านกำลังเขียนอยู่นี่ ในที่นี้ใช้ Python 2.7 ซึ่งจะอยู่ที่บรรทัดแรกของไฟล์เสมอ เพื่อบอกให้ระบบปฏิบัติการทราบว่าต้องใช้ compiler ตัวไหนในการประมวลผล syntax ดังกล่าวนั่นเอง โดยในที่นี้เราใช้ Syntax  ของภาษา Python จึงควรเขียน Shebang ดังนี้
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/python
 
#!/usr/bin/python 2.3
 
#!/usr/bin/python 2.7
 
หรือ
 
#!/usr/bin/env python
 
#!/usr/bin/env python 3.4
 
#!/usr/bin/env python 3.5

โดยความแตกต่างของทั้งสองแบบก็คือ ถ้าหากว่าเครื่องของท่านติดตั้ง Python มากกว่า 1 version หมายถึงหลาย ๆ คนติดตั้งทั้ง Python 2.3 Python 2.7 และ Python 3.4 ลงในเครื่องเดียวกันซึ่งถ้าหากอ้างอิงถึงโดยหลักการ และสิ่งที่ควรจะเป็นเราควรจะใช้ #!/usr/bin/python หรือ #!/usr/bin/python 2.7 เพื่อระบุตัว compiler ไปเลยครับจะได้ไม่งง เพราะจะเป็นการตรวจสอบไปในตัวว่าถ้าหากจะประมวลผล code เหล่านี้จะต้องใช้ module อะไรบ้าง และระบบได้ดำเนินการติดตั้ง module เหล่านั้นเป็นที่เรียบร้อยแล้วหรือยังก่อนที่จะทำการ compile แต่สำหรับคนที่ใช้ #!/usr/bin/env python หรือ #!/usr/bin/env python 3.5 นั้นจะใช้เมื่อได้ติดตั้ง Python ไว้มากกว่า 1 version และเป็นการบอกตัวประมวลผลว่าจะใช้ environment แรกที่เจอใน $PATH เพื่อสั่งประมวลผล code เหล่านี้นั้นเอง (หากเขียนแล้วงง สอบถามเข้ามาได้นะครับบางทีผมแปลเป็นภาษาไทยแล้วไม่เข้าใจเอง เขียนแบบนี้แล้วเข้าใจกว่า เหอ ๆ ๆ ) โดยจริง ๆ แล้วไม่ว่าท่านจะติดตั้ง Python มากกว่า 1 version หรือไม่ก็สามารถใช้ #!/usr/bin/env python ได้อยู่ดี อีกอย่าง shabang ไม่ได้ส่งผลกระทบอะไรกับ code ที่เขียนเลย เพราะเป็นเพียงแค่ตัวระบุว่าจะใช้ compiler ตัวไหนประมวลผลไฟล์ code นี้เท่านั้น

เริ่มต้นเขียน Code กันเลยดีกว่า
ให้เราเปิดโปรแกรม text editor ขึ้นมาแล้วทำการ import mechanize module ตาม code ด้านล่างครับ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python
 
import mechanize
 
 
 
br = mechanize.Browser() #สังเกตุ B ของ Browser ต้องเป็นตัวใหญ่นะครับ
 
br.addheaders = [(‘user-agent’,’Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2593.0 Safari/537.36′)]
 
 
 
br.open(‘https://www.google.co.th’)
 
print br.response.read()

จาก code ข้างบนจะเป็นการ import Mechanize module เพื่อใช้งานใน code ของเรา บรรทัดถัดมาเป็นการสร้างตัวแปลแบบ Object ให้ชื่อว่า br ซึ่งมีคุณสมบัติเป็น browser นั่นเอง บรรทัดต่อไปก็เติม Header ลงไปเพื่อให้เขาเห็นเราเป็น web browser นั่นเองเพราะหากเราไม่ใส่ข้อมูลในส่วนนี้ web server ที่ถูก setup มาดีจะไม่ตอบครับ เพราะคิดว่าเราจะไปทำอะไรมิดีมิร้าย เพราะไม่ได้ใช้โปรแกรมประเภท Web Browser จริง ๆ ในการเข้าถึงเว็บไซต์นั่นเอง ในที่นี้เราใช้ Python 2.7 ถ้าไม่มีบรรทัดนี้มันจะไปขึ้นที่ Web Server ในส่วนของ User-Agent ว่า Python 2.7 เลยครับ เหอ ๆ ๆ บรรทัดถัดมาคือจะสร้างตัวแปร br เพื่อเปิดเว็บไซต์ของ google นั่นเอง และบรรทัดสุดท้ายให้ print ผลลัพธ์ออกมาให้ดูนั่นเอง โดยถ้าหากใครต้องการศึกษาการสร้างตัวแปรที่ใช้งานเกี่ยวกับ HTTP แบบตั้งแต่เริ่มต้นเพื่อให้เข้าใจการทำงาน Python ได้เตรียม Module ที่ชื่อ urllib ไว้ให้ได้ใช้งานกันนะครับ แต่อาจจะไม่ง่ายแบบ Mechanize นั่นเองแต่เป็นตัวเลือกที่ดีสำหรับผู้ที่ต้องการเข้าใจหลักการทำงานของมันครับ ผลลัพธ์ของ code ข้างบนจะประมาณนี้ครับ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Traceback (most recent call last):
 
File “D:\Workspace\Programming\Python\http\test.py”, line 7, in <module>
 
br.open(‘https://www.google.co.th’)
 
File “C:\Python27\lib\site-packages\mechanize\_mechanize.py”, line 203, in open
 
return self._mech_open(url, data, timeout=timeout)
 
File “C:\Python27\lib\site-packages\mechanize\_mechanize.py”, line 255, in _mech_open
 
raise response
 
mechanize._response.httperror_seek_wrapper: HTTP Error 403: request disallowed by robots.txt
 
[Finished in 0.6s with exit code 1]</module>

เนื่องจากว่า google มีการใช้ robot ในการติดตามเรา แต่เราไม่รู้ว่าจะโต้ตอบยังไงกับ robots.txt ของ google มันเลยดีดเราทิ้งโดยมีสองเงื่อนไขคือ เราไม่ผ่านการตรวจสอบ หรือไม่ได้รับสิทธิในการเข้าถึงหน้าดังกล่าวจะขึ้น error 403 ครับ สิ่งที่เราร้องขอไม่ได้รับอนุญาตให้ดำเนินการเช่น เราต้องการเรียกดู Direcotory Listing ซึ่ง Web Server ไม่อนุญาตจะขึ้น error 403 เช่นกันครับ ดังนั้นเราจึงต้องใช้ code เพิ่มไปอีกหน่อยเพื่อให้สามารถโต้ตอบกับเจ้า robots.txt ได้ครับตาม code ด้านล่างครับ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python
 
import mechanize
 
 
 
br = mechanize.Browser()
 
br.addheaders = [(‘user-agent’,’Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2593.0 Safari/537.36′)]
 
br.set_handle_redirect(True) #follow redirect
 
br.set_handle_robots(False) # ignore robots
 
br.open(‘https://www.google.co.th’)
 
print br.response.read()

เราเพิ่มบรรทัด br.set_handle_redirect(True) #follow redirect เผื่อว่ามีการ redirect ไปที่หน้าใด ๆ ที่เว็บเค้าตั้งไว้มันจะตามไปที่หน้านั้นครับเช่น เวลาที่เรา login เข้าไปในเว็บไซต์แล้วมันจะ redirect ไปที่หน้า index.php เจ้า br ก็จะตามไปที่หน้า index.php ด้วยนั่นเองครับ อีกบรรทัดที่เพิ่มไปคือ br.set_handle_robots(False) # ignore robots เพื่อให้เราไม่สนใจเจ้า robots.txt และดำเนินการร้องขอหน้าเว็บตามที่เราต้องการต่อไปเลยนั่นเองครับ ผลลัพธ์จากการใส่สองบรรทัดนี้คือเราจะได้โค้ดของหน้า google.co.th มาครับดังตัวอย่างด้านล่างครับ
1
2
3
4
5
6
7
8
9
<!doctype html><html itemscope=”” itemtype=”http://schema.org/WebPage&#8221; lang=”th”><head><meta content=”/images/branding/googleg/1x/googleg_standard_color_128dp.png” itemprop=”image”><link href=”/images/branding/product/ico/googleg_lodp.ico” rel=”shortcut icon”><meta content=”origin” id=”mref” name=”referrer”><title>Google</title> <script>
(function(){window.google={kEI:’wEorWJSgN8jovATC_Zgg’,kEXPI:’750721,1351903,1352083,1352266,3700278,4026240,4029815,4031109,4032677,4036527,4038012,4038214,4038394,4039268,4041776,4043041,4043492,4045096,4045293,4045841,4046043,4046835,4046837,4046904,4047140,4047454,4047593,4048347,4048980,4049063,4050750,4051887,4052304,4052811,4056126,4056682,4058016,4059817,4061666,4061980,4062724,4064468,4064796,4065787,4065918,4066727,4068291,4068550,4068560,4069772,4069829,4069839,4069840,4070143,4071387,4072270,4072364,4072602,4072776,4073405,
4073418,4073959,4074149,4074174,4074177,4074597,4076096,4076759,4076931,4076998,4077777,4078407,4078438,4078457,4078588,4078763,4079081,4079105,4079206,4079626,4080167,4080629,4080760,4081037,4081038,4081264,4081471,4081482,4082140,4082219,4082230,4082309,4082402,4082618,4083282,4083476,4083517,4083970,4084247,4084255,4084343,4084366,4084956,4085014,4085181,4085335,4085444,4085476,4085627,4085809,4085860,4086085,4086171,4086521,4087054,4087182,4087709,8300272,8300471,8502184,8502648,8503585,8504846,8504935,8505150,8505152,8505259,8505275,8506340,8506399,8506478,8506615,8507098,8507380,8507460,8507689,8507846,8507896,8508066,8508177,8508229,8508298,8508351,8508395,8508421,8508564,10200083,16200027′,authuser:0,j:{en:1,bv:24,pm:’
p’,u:’c9c918f0′,qbp:0},kscs:’c9c918f0_24′};google.kHL=’th’;})();(function(){google.lc=[];google.li=0;google.getEI=function(a){for(var b;a&&(!a.getAttribute||!(b=a.getAttribute(“eid”)));)a=a.parentNode;return b||google.kEI};google.getLEI=function(a){for(var b=null;a&&(!a.getAttribute||!(b=a.getAttribute(“leid”)));)a=a.parentNode;return
b};google.https=function(){return”https:”==window.location.protocol};google.ml=function(){return null};google.wl=function(a,b){try{google.ml(Error(a),!1,b)}catch(c){}};google.time=function(){return(new Date).getTime()};google.log=function(a,b,c,e,g){a=google.logUrl(a,b,c,e,g);if(“”!=a){b=new Image;
var d=google.lc,f=google.li;d[f]=b;b.onerror=b.onload=b.onabort=function(){delete d[f]};window.google&&window.google.vel&&window.google.vel.lu&&window.google.vel.lu(a);b.src=a;google.li=f+1}};google.logUrl=function(a,b,c,e,g){var d=””,f=google.ls||””;if(!c&&-1==b.search(“&ei=”))
{var h=google.getEI(e),d=”&ei=+h;-1==b.search(“&lei=”)&&((e=google.getLEI(e))?d+=”&lei=+e:h!=google.kEI&&(d+=”&lei=+google.kEI))}a=c||”/+(g||”gen_204″)+”?atyp=i&ct=+a+”&cad=+b+d+f+”&zx=+google.time();/^http:/i.test(a)&&google.https()&&(google.ml(Error(“a”),!1,{src:a,glmm:1}),a=””);return a};google.y={};google.x=function(a,b){google.y[a.id]=[a,b];return!1};google.lq=[];google.load=function(a,b,c){google.lq.push([[a],b,c])};google.loadAll=function(a,b){google.lq.push([a,b])};})();
 
google.j.b=(!!location.hash&&!!location.hash.match(‘[#&]((q|fp)=|tbs=rimg|tbs=simg|tbs=sbi)’))………….ยาวไปขอตัดออกครับ

ตามนี้นะครับ เราก็จะสามารถเปิดเว็บด้วย Python script ได้แล้ว สะดวกมว๊ากกกกกกกก จากบรรทัดนี้ไปจะเป็น Cheat Sheet นะครับซึ่งจะรวมคำสั่งที่ Mechanize มีให้ใช้เพื่อความสะดวกครับซึ่งผมแปลมาจากลิงค์ที่ผมหาเจอนะครับหากท่านใดสนใจเข้าไปอ่านที่ต้นฉบับคลิก ที่นี่ และหากแปลผิดนี่ขออภัยด้วยนะครับ โง่ภาษาอังกฤษมว๊ากกกกกก สร้าง object ของ Mechanize
1
2
3
4
5
6
7
response = br.open(url)
 
print response.read() # the text of the page
 
response1 = br.response() # get the response again
 
print response1.read() # can apply lxml.html.fromstring()
การใช้ form เพื่อค้นหา form ที่ต้องการกรอกข้อมูล
1
2
3
4
5
for form in br.forms():
 
print “Form name:”, form.name
 
print form
หากต้องการเลือก form
1
2
3
br.select_form(“form1”) # ใช้เมื่อใน code มีการใส่ชื่อของ form นั้น ๆ
 
br.form = list(br.forms())[0] # ใช้เมื่อใน code ไม่มีการตั้งชื่อ form โดยตัวเลขด้านหลังเปรียบเสมือนเลขลำดับของ form เหล่านั้น ตัวอย่างเป็น form 0 หมายถึง form แรกสุดของ code นั่นเอง
การใช้ Control
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for control in br.form.controls:
 
print control
 
print type=%s, name=%s value=%s” % (control.type, control.name, br[control.name])
 
 
 
control = br.form.find_control(“controlname”) #ใช้ในกรณีที่มีการตั้งชื่อไว้
 
 
 
if control.type == “select”: # means it’s class ClientForm.SelectControl
 
for item in control.items:
 
print ” name=%s values=%s” % (item.name, str([label.text for label in item.get_labels()])) # ใช้สำหรับให้ตัว control บอกเราว่ามีค่าอะไรอยู่บ้าง
ซึ่ง select type สามารถมีได้มากกว่าค่าเดียว
1
2
3
4
5
6
7
8
9
print control.value
 
print control # selected value is starred
 
control.value = [“ItemName”]
 
print control
 
br[control.name] = [“ItemName”] # equivalent and more normal
และสามารถเลือกให้ text control แสดงค่าเป็น string ได้
1
2
3
4
5
if control.type == “text”: # means it’s class ClientForm.TextControl
 
control.value = “stuff here”
 
br[“controlname”] = “stuff here” # equivalent
ตั้งค่า Control ให้เป็นแบบ Read Only
1
2
3
control.readonly = False
 
control.disabled = True
หรือจะ Disable Control Type ทั้งหมด
1
2
3
4
5
for control in br.form.controls:
 
if control.type == “submit”:
 
control.disabled = True
การ Submit Form
1
2
3
4
5
response = br.submit()
 
print response.read()
 
br.back() # go back
หรืออาจจะใส่ br.method = “POST” เพื่อระบุ HTTP Method ให้กับ Object ได้ทันทีครับ
การค้นหา และแสดง Link
1
2
3
for link in br.links():
 
print link.text, link.url
การคลิกลิงค์
1
2
3
4
5
request = br.click_link(link)
 
response = br.follow_link(link)
 
print response.geturl()
หมดแล้วตี 1 กว่า ๆ แล้วจะนอนแล้วครับไว้มาเขียนใหม่

No comments:

Post a Comment

วิธีการติดตั้ง และตั้งค่า Apache2 พร้อมเปิดใช้งาน HTTPS ด้วยวิธี Self-Sign บน Ubuntu 18.04.1 LTS

ดีจร้า วันนี้ช่วงเช้าว่างเลยมาเขียนบทความเพิ่มเติมเกี่ยวกับการติดตั้ง และตั้งค่า Apache2 ให้สามารถใช้งานผ่าน HTTPS ได้กันมาเริ่มกันเลยครับ ...