บันทึกเกร็ดเกี่ยวกับการใช้ไพธอนทำเว็บ ด้วย cgi
Content-type: text/html\r\n
เป็นบรรทัดแรก apache ถึงจะตีความเป็น HTML#!/usr/bin/env python print "Content-type: text/html\r\n" ...
#!/usr/bin/env python # -*- coding: utf8 -*- ...
from ... import *
และ import ...
เช่นสมมุติแพกเกจเราชื่อ dweb ใช้... import dweb from dweb import * ...
$ vi .htaccess
DirectoryIndex index.py Options +Indexes ExecCGI FollowSymLinks MultiViews AddHandler cgi-script .py AddType application/x-python-code .pyc .pyo AddHandler python-program .pyc .pyo
การใช้โมดูล cgi ในการสร้างเว็บ ต้องระวังเรื่องเนื้อหาในเพจให้ดี
ให้ระวังคือ
ไม่งั้นฟังก์ชั่น cgi.FieldStorage จะทำงานผิดพลาดไปหมด ดีบักยากด้วย เพราะแสดงผลออกมาถูก แต่การทำงานภายในผิดหมด
เอามาจาก ug's Python CGI scripts: cookie.py
การเซ็ต Cookie
สร้างไฟล์ชื่อ setcookie.py
#!/usr/bin/env python import Cookie c1 = Cookie.SimpleCookie() # Create a cookie in c1 # This will be temporary and will disappear when the session is closed c1["cracker"] = "hello" # The RFC says you should always set this but it seems to work ok without it c1["cracker"]["version"] = 1 # Create another one c1["bisquit"] = "whatever" # Make the browser store it for one hour c1["bisquit"]["max-age"] = 3600 # Time to keep, in seconds c1["bisquit"]["expires"] = 3600 # Obsolete, but Netscape still seems to require it c1["bisquit"]["version"] = 1 # Print the headers that sets the cookies print c1 # Show html page print "Content-type: text/html\r\n" print "<h1>Cookie is set</h1>"
สั่งรันจากบราวเซอร์หนึ่งครั้ง Cookie จะถูกเก็บเข้าในเครื่องของ Client
การรับ Cookie
สร้างไฟล์ชื่อ getcookie.py
#!/usr/bin/env python import Cookie, os # Show html page print "Content-type: text/html\r\n" print "<h1>Get cookie</h1>" try: cookie = os.environ["HTTP_COOKIE"] print "HTTP_COOKIE="+cookie print "<p>" c2 = Cookie.SimpleCookie() c2.load(os.environ["HTTP_COOKIE"]) print "<pre>" print c2 print "</pre>" print 'c2["bisquit"].value =', c2["bisquit"].value, "<br />\n" print 'c2["cracker"].value =', c2["cracker"].value except: print "No cookies were received"
สั่งรันจากบราวเซอร์ จะเห็นตัวแปร bisquit
และ cracker
ที่เราใส่ไว้
อ่าน Dive Into Python เห็นตัวอย่างฟังก์ชั่น Info
เลยประยุกต์มาทำบนเว็บครับ
เผื่อจะขยายไปเป็น search help
ทดลองทำ syntax highlight โดยลอกจาก โมดูล GeSHiFilter ของ drupal ซึ่งเอามาจากโค๊ด PHP ที่ GeSHi อีกทีนึง แก้ปรับสี css นิดเดียว
ทดลองดูซอร์สได้ดังนี้
ตอนนี้ทำได้แค่ไพธอนภาษาเดียว และน่าจะยังมีบั๊กอยู่เยอะ จะค่อย ๆ ปรับปรุงไปเรื่อย ๆ ครับ
ยังไม่รู้ว่าโค๊ดของโมดูลหลัก dweb จะเปลี่ยนแปลงไปยังไงนะครับ แต่ตอนนี้โพสต์แบบนี้ไปก่อน
เราสามารถใช้ python อ่านเนื้อหาจากเว็บได้โดยใช้โมดุล urllib
เอาตัวอย่างจาก Dive into Python - 11.2. How not to fetch data over HTTP
>>> import urllib >>> data = urllib.urlopen('http://diveintomark.org/xml/atom.xml').read() 1 >>> print data <?xml version="1.0" encoding="iso-8859-1"?> <feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en"> <title mode="escaped">dive into mark</title> <link rel="alternate" type="text/html" href="http://diveintomark.org/"/> <-- rest of feed omitted for brevity -->
ด้วยวิธีนี้เราสามารถนำเข้าไฟล์สตรีมทั้งหลายได้โดยสะดวก
จากตอนก่อน เราสามารถนำมาสร้างสคริปต์ง่าย ๆ เอาไว้เก็บเนื้อหาของหน้าเว็บได้ดังนี้
$ vi d.getweb.py
#!/usr/bin/env python # SAVE CONTENT OF WEB PAGE TO FILE import sys, os, urllib def usage(progname): print "Usage: %s URL FILENAME" % (progname) print "Save content of web page to file." def cannotopenfile(filename="",readwrite="r"): if readwrite=="r": msg=" reading" else: msg=" writing" print "Cannot open file %s for %s." % (filename, readwrite) def genfilename(filename="",ext="new"): if filename=="": return "" if ext.lower()!="new" and ext.lower()!="bak": ext="bak" if os.path.exists(filename+"."+ext): i=0 while os.path.exists(filename+"."+ext+str(i)) and (i < 1000): i=i+1 if i>999: return "" return filename+"."+ext+str(i) else: return filename+"."+ext # if __name__=="__main__": progname=os.path.basename(sys.argv[0]) try: url=sys.argv[1] filename=sys.argv[2] except: usage(progname) sys.exit(1) # try: if os.path.exists(filename): bakfile=genfilename(filename,"bak") os.rename(filename,bakfile) except: cannotopenfile(filename,"w") sys.exit(1) # try: data=urllib.urlopen(url).read() except: print "Cannot open %s." % (url) sys.exit(1) # f=open(filename,"w") f.write(data) f.close() print "Save %s to %s success." % (url, filename)
เรียกใช้งานด้วยคำสั่ง
./d.getweb.py http://WEB.TO.GET FILENAME.EXT
จากครั้งก่อน ที่ทำตัวแจงเมธอด ขยายมาเป็นตัวค้นหาและแสดงซอร์สโค๊ด
โดยใช้พร๊อพเพอตี้ __file__
ปกติเราดูซอร์สได้เองอยู่แล้ว แต่การนำมาลงเว็บให้ค้นได้ง่าย ๆ อาจช่วยทำให้เข้าใจการทำงานของโมดูลในไพธอนดียิ่งขึ้นครับ