Sunday, August 30, 2015

თავი12(12,3 - 12,4)



12.3 Retrieving an image over HTTP


ზემო მაგალითში მივიღეთ მარტივი ტექსტური ფაილი, რომელსაც ჰქონდა ახალი ხაზები და პროგრამის გაშვებისას ეკრანზე მარტივად დავაკოპირეთ მონაცემები. შეგვიძლია გამოვიყენოთ მსგავსი პროგრამა, რომ მივიღოთ გამოსახულება  HTTP - ის გამოყენებით. პროგრამის გაშვებისას ეკრანზე მონაცემების კოპირების ნაცვლად, მონაცემებს თავს ვუყრით სტრინგში, თავსართს ვაშორებთ და გამოსახულების მონაცემებს ვინახავთ:

import socket
import time

mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect(('www.py4inf.com', 80))
mysock.send('GET http://www.py4inf.com/cover.jpg HTTP/1.0\n\n')

count = 0
picture = "";
while True:
data = mysock.recv(5120)
if ( len(data) < 1 ) : break
# time.sleep(0.25)
count = count + len(data)
print len(data),count
picture = picture + data

mysock.close()

# Look for the end of the header (2 CRLF)
pos = picture.find("\r\n\r\n");
print 'Header length',pos
print picture[:pos]

# Skip past the header and save the picture data
picture = picture[pos+4:]
fhand = open("stuff.jpg","wb")
fhand.write(picture);
fhand.close()


პროგრამის გაშვებისას ამონაბეჭდი იქნება შემდეგი:

$ python urljpeg.py
2920 2920
1460 4380
1460 5840
1460 7300
...
1460 62780
1460 64240
2920 67160
1460 68620
1681 70301
Header length 240
HTTP/1.1 200 OK
Date: Sat, 02 Nov 2013 02:15:07 GMT
Server: Apache
Last-Modified: Sat, 02 Nov 2013 02:01:26 GMT
ETag: "19c141-111a9-4ea280f8354b8"
Accept-Ranges: bytes
Content-Length: 70057
Connection: close
Content-Type: image/jpeg

ამ ბმულისთვის Content-Type სათაური აჩვენებს, რომ დოკუმენტის სხეული არის გამოსახულება (image/jpeg). პროგრამა როცა შესრულდება შეგეძლება ნახო გამოსახულება stuff.jpg - ის გახსნით.

პროგრამის გაშვებისას ნახავ, რომ ყოველ ჯერზე როცა კი recv() მეთოდს გამოვიძახებთ  5120 სიმბოლოს არ ვიღებთ. ვიღებთ იმდენ სიმბოლოს, რამდენიც ქსელის საშუალებით გამოგზავნა ვებ სერვერმა იმ მომენტისთვის, როცა გამოვიძახეთ recv().  ამ მაგალითში მივიღეთ 1460 ან 2920 სიმბოლო ყოველ ჯერზე, როცა მოვითხოვეთ 520 სიმბოლოს მონაცემები.

შედეგი შეიძლება იყოს განსხვავებული რაც დამოკიდებულია შენი ქსელის სიჩქარეზე.
recv() - ის ბოლო გამოძახებისას მივიღეთ 1681 ბიტი რაც არის სტრიმის ბოლო და recv() - ის შემდეგ გამოძახებისას ვიღებთ ცარიელ სტრინგს, რაც ნიშნავს რომ სერვერმა სოკეტის ბოლოში გამოიძახა close(), რაც ნიშნავს რომ მეტი მონაცემი აღარაა.
შეგვიძლია recv() - ის მომდევნო გამოძახებები შევანელოთ time.sleep() - ის დეკომენტირებით(uncommenting). ამ მეთოდით გამოძახებებს შორის დრო იქნება წამის მეოთხედი, ასე რომ სერვერს ექნება უფრო მეტი მონაცემების გამოგზავნის საშუალება სანამ ხელახლა გამოვიძახებთ recv() - ის. ამ შეყოვნებით პროგრამის ამონაბეჭდი იქნება შემდეგი:

$ python urljpeg.py
1460 1460
5120 6580
5120 11700
...
5120 62900
5120 68020
2281 70301
Header length 240
HTTP/1.1 200 OK
Date: Sat, 02 Nov 2013 02:22:04 GMT
Server: Apache
Last-Modified: Sat, 02 Nov 2013 02:01:26 GMT
ETag: "19c141-111a9-4ea280f8354b8"
Accept-Ranges: bytes
Content-Length: 70057
Connection: close
Content-Type: image/jpeg


recv() - ის პირველი და ბოლო გამოძახების გარდა ახლა უვე ვიღებთ 5120 სიმბოლოს მონაცემების მოთხოვნისას.
აქ არის ბუფერი სერვერის send() მოთხოვნასა და ჩვენი აპლიკაციის recv() მოთხოვნას შორის. როცა პროგრამას ვუშვებთ ჩაშენებული „დაყოვნებით“, რაღაც მომენტში სერვერმა შეიძლება სოკეტში ბუფერი გაავსოს და იძულებული გახდეს გაჩერდეს სანამ ჩვენი პროგრამა არ დაიწყებს ბუფერის დაცლას. აპლიკაციის გაგზავნისას ან მიღებისას ასეთ შეჩერებას ქვია „დინების კონტროლი“ (flow control).


12.4 Retrieving web pages with urllib

სანამ ხელივ ვგზავნით და ვიღებთ მონაცემებს HTTP - ში სოკეტ ბიბლიოთეკის გამოყენებით,  პითონში არსებობს უფრო მარტივი გზა ამ დავალების შესასრულებლად - urllib-ის გამოყენება.
urllib-ის გამოყენებით ვებ გვერდებს შეგიძლია მოექცე როგორც ფაილს. მიუთითებ რომელი ვებ გვერდის მიღება გინდა და urllib გააკეთებს ყველაფერს.
ვებ გვერდიდან romeo.txt - ის წასაკითხი კოდის ტოლფასია შემდეგი კოდი:

import urllib

fhand = urllib.urlopen('http://www.py4inf.com/code/romeo.txt')
for line in fhand:
print line.strip()

როცა ვებ გვერდს გავხსნით urllib.urlopen - ით, უკვე შეგვიძლია მას მოვექცეთ, როგორც ფაილს და წავიკითხოთ for მარყუჟით.

როცა პროგრამა გაშვებულია ვხედავთ ფაილის შიგთავსის ამონაბეჭდს. „სათაურები“ მაინც გამოიგზავნა, მაგრამ urllib კოდმა „გაანადგურა“ და დააბრუნა მხოლოდ მონაცემები.

But soft what light through yonder window breaks
It is the east and Juliet is the sun
Arise fair sun and kill the envious moon
Who is already sick and pale with grief


როგორც მაგალითი შეგვიძლია დავწეროთ პროგრამა  romeo.txt - ში მონაცემების საპოვნელად და ყოველი სიტყვის გამოყენების რაოდენობის დასათვლელად:


import urllib

counts = dict()
fhand = urllib.urlopen('http://www.py4inf.com/code/romeo.txt')
for line in fhand:
    words = line.split()
    for word in words:
        counts[word] = counts.get(word,0) + 1
print counts


კიდევ ერთხელ:  ვებ გვერდის გახსნის შემდეგ მას ვკითხულობთ როგორც ლოკალურ ფაილს.