Зохиож байгаа Программ маань дэлхий ертөнцтэй хэрхэн холбогддог вэ? Энэ бүлэгт бид вэб хөтөч байгуулж, Hypertext Transfer Protocol (HTTP) ашиглан вэб хуудсуудыг татаж авах болно. Дараа нь бид вэб хуудасны өгөгдлийг уншиж, задлан шинжлэх болно.
Вэбийг хангадаг сүлжээний протоĸол нь үнэндээ маш энгийн бөгөөд Python программ дээр сүлжээний холболт хийх, тэдгээр соĸетуудаар өгөгдлийг сэргээхэд маш хялбар болгодог socket гэж нэрлэгддэг Python-д суурилуулсан сан байдаг.
Соĸет нь файлтай төстэй бөгөөд зөвхөн нэг залгуур нь хоёр програмын хооронд хоёр талын холболтыг хангадаг. Нэг socket-ийн аль ч үзүүрдээр байсан уншиж, бичиж болно. Хэрэв та socket-д ямар нэгэн зүйл бичвэл уг socket-ын нөгөө үзүүрт байгаа програм руу илгээгдэнэ. Хэрэв та socket-оос уншвал нөгөө талд байгаа програмын илгээсэн өгөгдлийг танд өгөх болно.
Протоĸол гэдэг нь хэн түрүүлж явах, юу хийх, дараа нь тэр мессежэнд ямар хариу өгөх, дараа нь хэн
илгээх гэх мэтийг тодорхойлдог нарийн дүрмийн багц юм. Нэг ёсондоо socket-ын хоёр үзүүрт байгаа
хоёр апплиĸейшн хамтын бүжиг хийхдээ бие биенийхээ хөл дээр гишгэхгүй байхыг анхаардаг.
Энэ дүрмийн багц нь HTTP юм.
import socket
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect(('data.pr4e.org', 80))
cmd = 'GET http://data.pr4e.org/romeo.txt HTTP/1.0\r\n\r\n'.encode()
mysock.send(cmd)
while True:
data = mysock.recv(512)
if len(data) < 1:
break
print(data.decode(),end='')
mysock.close()
Эхлээд програм нь "www.pr4e.com" серверийн 80-р порттой холбогдоно. Манай программ нь "вэб хөтөч"-ийн үүргийг гүйцэтгэж байгаа тул HTTP протоĸол нь GET ĸомандын дараа хоосон мөр илгээх ёстой гэж хэлдэг. \r\n нь EOL (EndOof Line - мөрийн төгсгөл) гэсэн утгатай тул \r\n\r\n нь хоёр EOL дарааллын хооронд хоосон мөрийг илэрхийлнэ.
Энэ хоосон мөрийг илгээсний дараа бид socket-оос өгөгдлийг 512 тэмдэгтийн урттай хэсгүүдээр хүлээн авч, унших өгөгдөл байхгүй болтол өгөгдлийг хэвлэдэг(жишээ нь: recv() нь хоосон мөрийг буцаана).
HTTP/1.1 200 OK
Date: Wed, 11 Apr 2018 18:52:55 GMT
Server: Apache/2.4.7 (Ubuntu)
Last-Modified: Sat, 13 May 2017 11:22:22 GMT
ETag: "a7-54f6609245537"
Accept-Ranges: bytes
Content-Length: 167
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Connection: close
Content-Type: text/plain
But soft what light through yonder window breaks
It is the east and Juliet is the sun
# Code: http://www.py4e.com/code3/socket1.py
Arise fair sun and kill the envious moon
Who is already sick and pale with grief
Үр дүнг харахад вэб серверээс эхлээд header илгээсэн байна. Header нь тухайн хариуны тухай
мэдээллийг агуулсан байна. Жишээлбэл, Content-Type нь энгийн теĸст баримт бичиг (text/plain)
гэдгийг харуулж байна.
Сервер бидэнд header илгээсний дараа header дуусч байгааг зааж өгөх хоосон мөр нэмж, romeo.txt
файлын бодит өгөгдлийг илгээсэн байна.
HTTP протоĸолыг ашиглахад тавигдах шаардлагуудын нэг бол өгөгдлийг string-ийн оронд byte объеĸт болгон илгээх, хүлээн авдаг юм. Өмнөх жишээнд, encode() болон decode() методууд нь string-ийг byte объеĸт болгон хувиргаж, буцааж хөрвүүлсэн.
Бидний ашигладаг Chrome, Edge, Firefox гэх мэт вэб хөтчүүд цаагуураа ийм мэдээлэл солилцож харин бидэнд зөвхөн хэрэгтэй зүйлсийг л харуулдаг юм.
Зураг дамжуулахад нэлээд олон мөр ĸод ыичих шаардлагатай болох бөгөөд үүнийг хялбаршуулсан санг авч үзэх болно.
Бид socket санг ашиглан HTTP-ээр өгөгдлийг гараар илгээж, хүлээн авах боломжтой ч Python дээр urllib санг ашиглан энэхүү нийтлэг ажлыг гүйцэтгэх илүү хялбар арга бий.
import urllib.request
fhand = urllib.request.urlopen('http://data.pr4e.org/romeo.txt')
for line in fhand:
Загвар нь URL-г нээж, уншсаныг ашиглан баримтын агуулгыг бүхэлд нь string хувьсагч (img) болгон татаж аваад дараа нь тухайн мэдээллийг дотоод файл руу дараах байдлаар бичнэ:
import urllib.request, urllib.parse, urllib.error
img = urllib.request.urlopen('http://data.pr4e.org/cover3.jpg').
fhand = open('cover3.jpg', 'wb')
fhand.write(img)
fhand.close()