Гузариш ба мундариҷа
Мавзӯи 6 аз 6

Сессияҳо, файлҳо ва қурб дар давра

Чаро ҳолатро нигоҳ дошта, қисм ба қисм мехонем

Муштарии воқеӣ кам як дархост мекунад: аввал танзимот мегирад ё ворид мешавад, баъд профил мехонад, ҳуҷҷат боргирӣ мекунад ва аз бойгонӣ мегузарад. Барои ин хотира байни дархостҳо, хондани сарфакоронаи файлҳои калон ва кори дуруст бо санаҳо лозим аст. Дар ин мавзӯъ ин усулҳоро якҷо карда, кори шабакаро аз коркарди маълумот фарқ мекунем.

Фарохониҳои ҷудогонаи requests.get ва requests.post ҳолати доимии муштараки сессия надоранд. Session дархостҳои вобастаро якҷо мекунад: cookie ва танзимоти умумиро нигоҳ дошта, аз маҷмӯи пайвастҳо истифода мебарад. Cookie ҷуфти ном ва қимат бо қоидаҳои фиристодан аст, ки сервер барои шинохтани муштарӣ дар дархостҳои баъдӣ медиҳад.

Муҳити cookie ва gzip

Блокҳоро бо тартиб дар як раванди Python иҷро кунед. Сервери маҳаллӣ файли шашбайтии бо gzip фишурдашударо медиҳад, cookie-и theme мегузорад ва cookie-и гирифтаашро нишон медиҳад. Ин интихоби омӯзишии намуди зоҳирист, на воридшавии воқеӣ ба сомона.

import gzip
import os
import threading
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import requests

os.environ["NO_PROXY"] = "127.0.0.1,localhost"

class Handler(BaseHTTPRequestHandler):
    def log_message(self, *args):
        pass

    def do_GET(self):
        data = gzip.compress(b"ABCDEF", mtime=0)
        self.send_response(200)
        self.send_header("Set-Cookie", "theme=blue; Path=/")
        self.send_header("X-Seen-Cookie", self.headers.get("Cookie", "-"))
        self.send_header("Content-Encoding", "gzip")
        self.send_header("Content-Length", str(len(data)))
        self.end_headers()
        self.wfile.write(data)

server = ThreadingHTTPServer(("127.0.0.1", 0), Handler)
threading.Thread(target=server.serve_forever, daemon=True).start()
base = f"http://127.0.0.1:{server.server_port}"
print(Handler.do_GET.__name__)

Барориш:

do_GET

Set-Cookie ба ҷавоби сервер тааллуқ дорад. Дар дархостҳои мувофиқи баъдӣ муштарӣ сарлавҳаи Cookie мефиристад. Қоидаҳои cookie домен, роҳ ва маҳдудиятҳои дигарро ба назар мегиранд; он танҳо луғате нест, ки бояд ба ҳар суроға фиристод.

Сессия дар хотир медорад, дархости ҷудогона не

Контексти with requests.Session() as s сессия месозад ва баъди блок мебандад. Дархостҳоро бо методҳои ҳамин сессия иҷро мекунанд: s.get, s.post. Сарлавҳаҳои умумиро ба s.headers илова мекунанд; дархости алоҳида онҳоро пурра ё иваз карда метавонад.

with requests.Session() as s:
    s.headers["X-Client"] = "study"
    first = s.get(base, timeout=5)
    second = s.get(base, timeout=5)
    print(first.headers["X-Seen-Cookie"])
    print(second.headers["X-Seen-Cookie"])
    print(s.cookies.get("theme"))
print(requests.get(base, timeout=5).headers["X-Seen-Cookie"])

Барориш:

-
theme=blue
blue
-

Дархости аввал ҳанӯз cookie надорад, дуюм аллакай theme=blue мефиристад. requests.get-и ҷудогонаи нав боз бе он оғоз мекунад. s.cookies cookie-ҳои ҷамъшудаи сессия, first.cookies бошад cookie-и ҳамин ҷавобро нигоҳ медорад. Дар воридшавии воқеӣ байни фиристодани парол ва хондани манбаи ҳифзшуда ҳамон сессияро нигоҳ дошта, ҳар ду ҷавобро санҷед.

Сессия ба ҷузвдони як муштарӣ монанд аст: дар он танзимоти умумӣ ва иҷозатномаҳои гирифташуда ҳастанд. Маҷмӯи пайвастҳо имкон медиҳад пайваст ба ҳамон сервер такроран истифода шавад, агар сервер ва протокол иҷозат диҳанд. Ин ваъдаи як пайвасти абадӣ нест. Баъди хондан ё бастани ҷавоб пайваст метавонад ба маҷмӯъ баргардад; ҷавоби ҷараёнии нобаста монеъ мешавад.

Файл байтҳост

Барои файли бинарии хурд r.content мувофиқ аст. r.text барои матн аст: табдили байтҳои номаълум метавонад аломатҳои ивазкунанда гузорад ва рамзгузории баръакс аслро барқарор намекунад. Тасвирҳо, бойгониҳо ва PDF-ро ҳамчун байт хонед; ҳангоми навиштан ба диск файлро бо wb кушоед.

Хондани ҷараёнӣ маъно дорад, ки бадан пеш аз оғози коркард пурра боргирӣ намешавад. stream=True хонданро ба таъхир меандозад, iter_content бошад қисмҳои байтҳоро медиҳад. Андозаи қисм танзими хондан аст, на сарҳади сабти мантиқӣ ва на ваъдаи дарозии якхелаи ҳамаи қисмҳо.

with requests.get(base, stream=True, timeout=(2, 5)) as r:
    r.raise_for_status()
    print(r.headers["Content-Encoding"])
    for chunk in r.iter_content(chunk_size=2):
        print(chunk)

Барориш:

gzip
b'A'
b'BC'
b'DE'
b'F'

Ҳарчанд сервер gzip фиристод, мо ABCDEF-и аслиро гирифтем: iter_content фишурдани дастгиришавандаи HTTP-ро худкор мекушояд. Дар боргирии воқеӣ ба ҷойи print(chunk) барои файли бо wb кушода f.write(chunk) нависед. Агар мақсад сарфаи хотира бошад, ҳамаи қисмҳоро дар рӯйхат ҷамъ накунед. Контексти with ҷавобро ҳатто ҳангоми истисно мебандад.

raw чӣ медиҳад

r.raw ҷараёни сатҳи поёнро медиҳад. Дар ин мисол raw.read() намоиши фишурдашударо бе кушодани худкор мехонад. Ин дастрасӣ кам лозим мешавад, вале фарқи байтҳои намоиши интиқолшуда ва байтҳои худи файлро мефаҳмонад.

with requests.get(base, stream=True, timeout=5) as r:
    compressed = r.raw.read()
print(compressed[:2].hex())
print(gzip.decompress(compressed))

Барориш:

1f8b
b'ABCDEF'

1f8b байтҳои аввали gzip аст. Content-Length-и сервер дарозии бадани фишурдаи фиристодашударо мегӯяд, бинобар ин баъди кушодан дарозии муҳтаво метавонад фарқ кунад. Бе ба назар гирифтани Content-Encoding онҳоро баробар нашуморед. Як ҷавобро беохир аз нав хонда намешавад: ҷараёни истеъмолшуда аллакай гузаштааст. Барои ҳар мисоли ҷудогона дархости нав мекунем.

Ҳосили санҷиш бе нигоҳ доштани тамоми файл

Hash натиҷаи кӯтоҳи ҳисоб аз пайдарпайии байтҳо аст. SHA-256 барои муқоиса бо ҳосили санҷишии интизорӣ ёрӣ медиҳад. Ҳар байт ва тартибаш муҳим аст. update-ро чанд бор фаро хондан мумкин: натиҷа мисли додани маълумоти якҷояшуда мешавад.

import hashlib

h = hashlib.sha256()
h.update(b"A")
h.update(b"BC")
print(h.hexdigest()[:16])
print(h.digest() == hashlib.sha256(b"ABC").digest())

Барориш:

b5d4045c3f466fa9
True

Мисол бо байтҳои тайёр кор мекунад, то hash-ро аз боргирӣ ҷудо кунад. Ҳангоми хондани ҷараёнӣ hash-ро бо ҳар қисм нав кардан мумкин аст. Сарҳади қисмҳо натиҷаро тағйир намедиҳад, вале қисми гумшуда ё гум шудани аломати сатри нав онро дигар мекунад. SHA-256-и пурра одатан 64 аломати шонздаҳӣ дорад; дар ин ҷо танҳо аввалаш барои барориши кӯтоҳ нишон дода шудааст. Hash бе намунаи боэътимод худ аз худ аслияти файлро исбот намекунад.

Санаҳо ва мушоҳидаҳои набуда

Барои бойгонӣ санаҳои тақвимӣ лозиманд, на арифметика бо сатрҳо. date рӯзро, timedelta(days=1) гузариш ба як рӯзро ифода мекунад. Python гузариши моҳ ва солро худаш ба назар мегирад. %Y/%m/%d барои роҳи бойгонӣ, %Y-%m-%d барои ҷадвал қулай аст.

from datetime import date, timedelta

day = date(2026, 1, 31)
print(f"{day:%Y/%m/%d}")
print(day + timedelta(days=1))
observations = {"2026-01-31": 0.0}
print(observations.get("2026-01-31") is None)
print(observations.get("2026-02-01") is None)

Барориш:

2026/01/31
2026-02-01
False
True

Мушоҳидаи сифрӣ вуҷуд дорад: is None онро аз набудан фарқ мекунад. Дар бойгонии омӯзишии қурб 404 маънои набудани сабти нав дар ҳамон рӯзро дорад. Аз рӯйи шарти масъалаҳо дар ин рӯз қимати охирини маълум истифода мешавад; мушоҳидаи наздиктарини пешина метавонад то оғози давраи интихобшуда бошад. Онро бо қимати оянда иваз накунед ва чуқурии ҷустуҷӯи додашударо риоя кунед.

Суроғаи бойгонӣ дар масъалаҳо шакли /archive/YYYY/MM/DD/daily_json.js дорад. Қимати пулӣ ба номинали дар JSON додашуда тааллуқ дорад. Қоидаи пур кардани ҷойҳои холӣ аз соҳаи кор вобаста аст: барои қурб қимати охирин муносиб аст, вале барои пешгӯии ҳаво қоидаи умумӣ нест. Аввал маънои набудани маълумотро муайян кунед.

Дар дохил чӣ рӯй медиҳад

Сессия дархостро бо танзимоти умумӣ омода мекунад, cookie-ҳои мувофиқро интихоб ва ҷавобро мегирад. Set-Cookie-ҳои нав анбори онро пур мекунанд. Бо stream=True бадан ҳангоми гузаштан аз iterator хонда мешавад; фишурдани HTTP метавонад пеш аз додани байтҳои навбатӣ кушода шавад. Баъд барнома алоҳида маълумот менависад, hash ҳисоб мекунад ё JSON таҳлил мекунад. Гузариши тақвимӣ ва интихоби мушоҳидаи охирин мантиқи барномаи шумост, на хусусияти requests.

Кори муҳити санҷишро анҷом медиҳем. Қимати -1 socket-и бастаро нишон медиҳад.

server.shutdown()
server.server_close()
print(server.fileno())

Барориш:

-1

Хатоҳои маъмул ва ислоҳи онҳо

  1. Барои ҳар дархост Session-и нав сохтан. Cookie дар сессияи пешина мемонад ва сервер муштариро намешиносад. Барои пайдарпайии вобаста як объект истифода баред.
  2. r.text.encode("utf-8") барои файли бинарӣ. Байтҳо метавонанд тағйир ёбанд. content ё iter_content хонед ва бо wb нависед.
  3. next(r.iter_content(...)) ҳамчун тамоми файл. Файли калон баъди қисми аввал бурида мешавад. Ҷараёнро то охир хонед.
  4. iter_lines() барои нусхаи дақиқи байтҳо. Метод ҷудокунандаҳои сатрро мепартояд ва андоза ва hash дигар мешаванд. Барои муҳтавои бинарӣ iter_content лозим аст.
  5. if rate барои мавҷудият ё ҷустуҷӯ танҳо дар дохили давра. Сифр набуда менамояд ва рӯзҳои аввал қимати пешинаро гум мекунанд. is not None-ро санҷед ва сарҳадҳои таърихро аз рӯйи шарт ба назар гиред.

Ёддошт

Чӣ лозим аст Восита
Танзимоти умумӣ ва cookie with requests.Session() as s
Cookie-и сессия / ҷавоб s.cookies / r.cookies
Файли бинарии хурд r.content
Файли калон stream=True, iter_content
Байтҳои сатҳи поён r.raw бо назардошти фишурдан
Нав кардани SHA-256 h.update(chunk)
Гузаштан ба рӯзи оянда day + timedelta(days=1)
Фарқ кардани набудан аз сифр value is None