Ачааллж байна...
Хоёр хичээлийн турш бид онол үзсэн: client, server, request, response, status code, endpoint, API.
Одоо код бичнэ.
Энэ хичээлд таны программ АНХ УДАА интернэтээс мэдээлэл авна. Тэр нь жинхэнэ өгөгдөл, жинхэнэ сервер, жинхэнэ мөч байх болно.
Тэр мөчийг би зохих ёсоор нь тэмдэглэмээр байна. Учир нь энэ бол таны программын хилийг өргөжүүлж байгаа хэрэг. Одоо хүртэл таны бүх программ ГАНЦААРАА ажиллаж байсан — өөрийн файл, өөрийн санах ой, өөрийн ертөнц.
Одоо тэр гадаад ертөнцтэй ярина.
Мөн энэ хичээлд Бүлэг 1-ийн зуршил ажилд орно: venv үүсгэх, идэвхжүүлэх, pip install хийх. Тэр үед би "энэ бол Бүлэг 11-д requests суулгах үед хэрэгтэй болно" гэж хэлсэн. Одоо тэр цаг ирлээ.
Алхам 1. Шинэ хавтас үүсгэнэ үү, жишээ нь api-dasgal.
Алхам 2. Тэр хавтсанд PowerShell нээнэ үү (File Explorer-ийн хаягийн мөрөнд powershell гэж бичээд Enter).
Алхам 3. Virtual environment үүсгэнэ:
powershell
python -m venv venvАлхам 4. Идэвхжүүлнэ:
powershell
.\venv\Scripts\Activate.ps1Алхам 5. (venv) бичиг мөрийн эхэнд гарч ирснийг НҮДЭЭРЭЭ баталгаажуулна уу:
(venv) PS C:\Users\Dulguun\Documents\python-advanced\api-dasgal>Энэ алхмыг алгасаж БОЛОХГҮЙ. Хэрэв (venv) байхгүй бол requests нь буруу газар суух болно.
(Хэрэв execution policy алдаа гарвал — Бүлэг 1.2-ыг эргэж хараарай: Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned)
Алхам 6. Одоо requests санг суулгана:
powershell
pip install requestsТерминал дээр татаж байгаа мэдээлэл урсаж, эцэст нь:
Successfully installed certifi-2024.7.4 charset-normalizer-3.3.2 idna-3.7 requests-2.32.3 urllib3-2.2.2Бүлэг 1.3-ээс танил үр дүн. Та зөвхөн requests -ыг гуйсан ч таван сан суусан — тэдгээр нь requests -ийн dependency (хамаарал) юм.
Алхам 7. Шалгана:
powershell
pip listrequests жагсаалтад байх ёстой.
Алхам 8. Мэргэжлийн зуршлыг бататгая — шаардлагаа тэмдэглэе:
powershell
pip freeze > requirements.txtАлхам 9. main.py нэртэй файл үүсгэнэ үү.
Хавтасны бүтэц:
api-dasgal/
├── venv/
├── requirements.txt
└── main.pyБүлэг 1-ийн бүх зуршил ажиллалаа. Тусдаа өрөө, зөв суулгасан сан, тэмдэглэсэн шаардлага.
Одоо хамгийн энгийн боломжит кодыг бичье.
python
# main.py
import requests
hariult = requests.get("https://api.open-meteo.com/v1/forecast?latitude=47.92&longitude=106.92¤t=temperature_2m")
print(hariult.status_code)
print(hariult.text)Ажиллуулна уу:
powershell
python main.py200
{"latitude":47.92,"longitude":106.92,"generationtime_ms":0.02,"utc_offset_seconds":0,"timezone":"GMT","timezone_abbreviation":"GMT","elevation":1301.0,"current_units":{"time":"iso8601","interval":"seconds","temperature_2m":"°C"},"current":{"time":"2026-07-13T14:00","interval":900,"temperature_2m":24.3}}ТА ИНТЕРНЭТЭЭС ӨГӨГДӨЛ ТАТЛАА.
Түр зогсоод, юу болсныг бодоорой.
Таны компьютер дээрх Python программ нь интернэтээр дамжуулан, өөр тивд байрлаж болох сервер рүү хүсэлт илгээж, Улаанбаатарын ОДООГИЙН температурыг авчирлаа. Тэр нь ойролцоогоор нэг секундэд болов.
200 — Бүлэг 11.1-ээс танил. Амжилттай.
Тэр тоо нь жинхэнэ. Хэрэв та энэ программыг маргааш ажиллуулбал — өөр тоо гарна. Учир нь цаг агаар өөрчлөгдөнө.
python
import requestsСан импортлож байна. pip install хийсэн тул ажиллана.
Хэрэв энд алдаа гарвал:
ModuleNotFoundError: No module named 'requests'Хэрэв
ModuleNotFoundErrorгарвал —(venv)идэвхтэй эсэхээ шалгаарай.
Бүлэг 1.3-ын стандарт сануулга. Тэр үед би "энэ сануулга Бүлэг 11-д дахин гарч ирнэ" гэж хэлсэн. Одоо тэр гарч ирлээ.
python
hariult = requests.get(url)requests.get() — GET хүсэлт илгээнэ (Бүлэг 11.1). Функцийн нэр нь method-ын нэртэй ижил байгааг анзаараарай.
Тэр нь RESPONSE ОБЪЕКТ буцаана. Тэр объект нь серверийн хариултын БҮХ мэдээллийг агуулна.
python
print(hariult.status_code).status_code — гурван оронтой тоо (Бүлэг 11.1). 200 бол амжилттай.
python
print(hariult.text).text — хариултын body -г STRING болгож өгнө.
Гэвч анзаараарай: тэр нь бүхэлдээ НЭГ урт мөр, уншихад аймшигтай. Түүнээс температурыг гаргаж авахын тулд string задлах хэрэгтэй болно.
Тэр бол буруу арга.
.json() — зөв аргаrequests сан нь илүү сайн зүйл өгдөг.
python
import requests
url = "https://api.open-meteo.com/v1/forecast?latitude=47.92&longitude=106.92¤t=temperature_2m"
hariult = requests.get(url)
uguudul = hariult.json()
print(type(uguudul))
print(uguudul)<class 'dict'>
{'latitude': 47.92, 'longitude': 106.92, 'generationtime_ms': 0.02, 'utc_offset_seconds': 0, 'timezone': 'GMT', 'timezone_abbreviation': 'GMT', 'elevation': 1301.0, 'current_units': {'time': 'iso8601', 'interval': 'seconds', 'temperature_2m': '°C'}, 'current': {'time': '2026-07-13T14:00', 'interval': 900, 'temperature_2m': 24.3}}.json() нь PYTHON DICTIONARY буцаалаа.
Одоо та Бүлэг 5-ын БҮХ мэдлэгээ ашиглаж чадна:
python
print(uguudul["latitude"])
print(uguudul["current"])
print(uguudul["current"]["temperature_2m"])47.92
{'time': '2026-07-13T14:00', 'interval': 900, 'temperature_2m': 24.3}
24.3Бүлэг 5.3-ын үүрлэсэн бүтэц. uguudul["current"]["temperature_2m"] — dictionary дотор dictionary.
Тэр үед би ингэж хэлсэн:
"ХАМГИЙН ЧУХАЛ: энэ бүтэц бол ЯГ JSON-ы хэлбэр. Та ЯГ ОДОО интернэтийн өгөгдлийг уншиж чадна."
Одоо та түүнийг үнэхээр уншиж байна.
.json() нь юу хийж байна вэ?
Тэр нь дотроо json.loads(hariult.text) дуудаж байна (Бүлэг 6.2). Өөрөөр хэлбэл:
Хариултын текстийг авна
JSON гэж задална
Python-ы бүтэц болгож буцаана
Бүлэг 6.2-т сурсан json.loads() нь энд ажиллаж байна — зөвхөн requests нь түүнийг таны өмнөөс дуудаж байна.
python
import requests
url = "https://api.open-meteo.com/v1/forecast?latitude=47.92&longitude=106.92¤t=temperature_2m,wind_speed_10m"
hariult = requests.get(url)
uguudul = hariult.json()
odoo = uguudul["current"]
negj = uguudul["current_units"]
print("=" * 40)
print("УЛААНБААТАР — ЦАГ АГААР")
print("=" * 40)
print(f"Цаг: {odoo['time']}")
print(f"Температур: {odoo['temperature_2m']}{negj['temperature_2m']}")
print(f"Салхи: {odoo['wind_speed_10m']} {negj['wind_speed_10m']}")
print("=" * 40)========================================
УЛААНБААТАР — ЦАГ АГААР
========================================
Цаг: 2026-07-13T14:00
Температур: 24.3°C
Салхи: 12.5 km/h
========================================Жинхэнэ программ. Жинхэнэ өгөгдөл.
current=temperature_2m,wind_speed_10m — таслалаар хоёр үзүүлэлт хүссэн.
API нь current_units гэсэн талбарт нэгжүүдийг ч бас өгч байгааг анзаараарай. Тэр нь маш сайн дизайн — програм нь нэгжийг таамаглах шаардлагагүй.
params= — цэвэрхэн аргаОдоохондоо бид URL -ыг ГАРААР бичсэн:
python
url = "https://api.open-meteo.com/v1/forecast?latitude=47.92&longitude=106.92¤t=temperature_2m"Энэ нь ажиллана, гэхдээ МУУ.
Хэдэн шалтгаанаар:
1. Уншихад хэцүү. Урт, нэг мөр, ? ба & тэмдгүүд холилдсон.
2. Динамик утга оруулахад аймшигтай. Хэрэв өргөрөг нь хувьсагч бол:
python
url = f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}¤t=temperature_2m"Одоо f-string дотор ? ба & — уншихад бүр ч хэцүү.
3. Тусгай тэмдэгт нь ЭВДЭРНЭ. Хэрэв утгад зай, кирилл үсэг, & тэмдэг байвал — URL эвдэрнэ.
Зөв арга: params= keyword argument.
python
import requests
url = "https://api.open-meteo.com/v1/forecast"
parametruud = {
"latitude": 47.92,
"longitude": 106.92,
"current": "temperature_2m,wind_speed_10m",
"timezone": "Asia/Ulaanbaatar",
}
hariult = requests.get(url, params=parametruud)
print(hariult.url)
print()
print(hariult.json()["current"])https://api.open-meteo.com/v1/forecast?latitude=47.92&longitude=106.92¤t=temperature_2m%2Cwind_speed_10m&timezone=Asia%2FUlaanbaatar
{'time': '2026-07-13T22:00', 'interval': 900, 'temperature_2m': 18.7, 'wind_speed_10m': 8.3}Хамаагүй цэвэрхэн.
params нь DICTIONARY — key нь параметрийн нэр, value нь утга.
requests нь тэр dictionary-г АВЧ, зөв форматтай URL болгож угсарна.
hariult.url нь эцсийн URL -ыг харуулж байна. Анзаараарай: %2C ба %2F гэсэн хачин тэмдэгтүүд гарч ирлээ.
Тэдгээр нь URL encoding юм. Зарим тэмдэгт (таслал, налуу зураас, зай) нь URL-д тусгай утгатай тул тэднийг ОРЛУУЛАХ хэрэгтэй:
, → %2C
/ → %2F
зай → %20
requests нь түүнийг АВТОМАТААР хийж байна. Хэрэв та URL -ыг гараар бичсэн бол — өөрөө хийх хэрэгтэй байх байсан. Тэр нь алдааны эх үүсвэр.
Дүрэм: query parameter -ыг ҮРГЭЛЖ params= -ээр дамжуул. URL -д гараар бүү бич.
Бүлэг 11.2-т би "query parameter нь keyword argument -тай ижил санаа" гэж хэлсэн. Одоо тэр нь шууд ижил бичлэг болов — dictionary дотор key=value.
Одоо params -ийн ачаар программ уян хатан болно:
python
import requests
def tsag_agaar_avakh(lat: float, lon: float) -> dict:
url = "https://api.open-meteo.com/v1/forecast"
parametruud = {
"latitude": lat,
"longitude": lon,
"current": "temperature_2m,wind_speed_10m",
"timezone": "auto",
}
hariult = requests.get(url, params=parametruud)
return hariult.json()
khotууd: dict[str, tuple[float, float]] = {
"Улаанбаатар": (47.92, 106.92),
"Дархан": (49.49, 105.92),
"Эрдэнэт": (49.03, 104.08),
"Токио": (35.68, 139.69),
"Лондон": (51.51, -0.13),
}
print("=" * 50)
for khot, (lat, lon) in khotууd.items():
uguudul = tsag_agaar_avakh(lat, lon)
odoo = uguudul["current"]
print(f"{khot:<15} {odoo['temperature_2m']:>6.1f}°C салхи {odoo['wind_speed_10m']:>5.1f} км/ц")
print("=" * 50)==================================================
Улаанбаатар 18.7°C салхи 8.3 км/ц
Дархан 17.2°C салхи 6.1 км/ц
Эрдэнэт 16.9°C салхи 7.4 км/ц
Токио 28.4°C салхи 11.2 км/ц
Лондон 21.3°C салхи 9.8 км/ц
==================================================
==================================================Таван хот, таван API дуудалт, нэг loop.
Кодыг задалъя:
khotууd: dict[str, tuple[float, float]] — Бүлэг 5.1-ийн tuple нь координатыг илэрхийлж байна. Тогтмол бүтэц (үргэлж хоёр тоо), өөрчлөгдөшгүй.
for khot, (lat, lon) in khotууd.items(): — Бүлэг 2.5-ын давхар unpacking! Гадна нь key-value, дотор нь tuple.
{odoo['temperature_2m']:>6.1f} — Бүлэг 6.4-ийн формат заагч.
"timezone": "auto" — API нь координатаас цагийн бүсийг ӨӨРӨӨ таана. Гоё зүйл.
Хэдэн бүлгийн мэдлэг нэг программд нийллээ.
Дээрх код нь таван хүсэлт илгээв. Тэр нь ЗҮГЭЭР.
Гэвч анхаараарай: хэрэв та мянган хот давтвал — мянган хүсэлт илгээнэ. Тэр нь:
1. УДААН. Хүсэлт бүр 0.5-2 секунд. Мянга нь 10-30 минут.
2. Сервер таныг ХОРИГЛОЖ болно. Бүлэг 11.1-ээс:
429 Too Many Requests — "Хэт олон хүсэлт." Үнэгүй API-ууд ихэвчлэн хязгаартай байдаг.
3. Эелдэг БУС. Сервер нь үнэгүй ажиллаж байна. Түүнийг бөмбөгдөх нь буруу.
Практик дүрмүүд:
Loop дотор API дуудахдаа БОЛГООМЖТОЙ бай
Хэрэв олон дуудалт хэрэгтэй бол — хүлээлт нэм (time.sleep(0.5))
Ижил өгөгдлийг ДАХИН татахгүй бай — хадгал (файлд, эсвэл санах ойд)
Documentation-оос хязгаарыг шалга
Open-Meteo нь үнэгүй, өдөрт 10,000 хүсэлт зөвшөөрдөг — бидний хэрэгцээнд хангалттай.
Одоо интерактив болгоё. Гэхдээ шинэ асуудал гарна: хэрэглэгч координат мэдэхгүй. Тэр "Улаанбаатар" гэж бичихийг хүсэж байна.
Аз болоход Open-Meteo нь ХАЙЛТЫН API ч бас өгдөг — тэр нь хотын нэрээс координат олно.
python
import requests
def khot_khaikh(ner: str) -> dict | None:
url = "https://geocoding-api.open-meteo.com/v1/search"
parametruud = {"name": ner, "count": 1, "language": "en"}
hariult = requests.get(url, params=parametruud)
uguudul = hariult.json()
ur_dun = uguudul.get("results")
if not ur_dun:
return None
return ur_dun[0]
def tsag_agaar_avakh(lat: float, lon: float) -> dict:
url = "https://api.open-meteo.com/v1/forecast"
parametruud = {
"latitude": lat,
"longitude": lon,
"current": "temperature_2m,wind_speed_10m",
"timezone": "auto",
}
return requests.get(url, params=parametruud).json()
khotiin_ner = input("Хотын нэр (англиар): ").strip()
khot = khot_khaikh(khotiin_ner)
if khot is None:
print(f"'{khotiin_ner}' гэсэн хот олдсонгүй.")
else:
print(f"\nОлдлоо: {khot['name']}, {khot.get('country', '')}")
print(f"Координат: {khot['latitude']}, {khot['longitude']}")
tsag_agaar = tsag_agaar_avakh(khot["latitude"], khot["longitude"])
odoo = tsag_agaar["current"]
print()
print("=" * 40)
print(f"{khot['name'].upper()}")
print("=" * 40)
print(f"Температур: {odoo['temperature_2m']}°C")
print(f"Салхи: {odoo['wind_speed_10m']} км/ц")
print("=" * 40)Хотын нэр (англиар): Ulaanbaatar
Олдлоо: Ulaanbaatar, Mongolia
Координат: 47.90771, 106.88324
========================================
ULAANBAATAR
========================================
Температур: 18.7°C
Салхи: 8.3 км/ц
========================================ХОЁР API-г ГИНЖЛЭВ. Эхнийх нь координат олсон, хоёр дахь нь тэр координатаар цаг агаар авсан.
Энэ бол бодит программын хэв маяг. Нэг API-гийн гаралт нь нөгөөгийн оролт болно.
ur_dun = uguudul.get("results") — Бүлэг 4.3-ын .get(). Хэрэв хот олдоогүй бол API нь "results" талбарыг ОРУУЛДАГГҮЙ. .get() нь None буцаана, KeyError гарахгүй.
Бүлэг 5.3-ын сургамж: "Бодит өгөгдөлд key байхгүй байж болно → .get(key, default) ашигла."
-> dict | None (Бүлэг 4.3) — функц нь "хот ЭСВЭЛ юу ч биш" буцаана. Дуудагч шалгах ёстой.
if khot is None: — шалгалт. Программ унахгүй.
requests.get() -ийн буцаасан объектод илүү олон зүйл байна:
python
import requests
hariult = requests.get("https://api.open-meteo.com/v1/forecast?latitude=47.92&longitude=106.92¤t=temperature_2m")
print(f"Status code: {hariult.status_code}")
print(f"URL: {hariult.url}")
print(f"Encoding: {hariult.encoding}")
print(f"Хугацаа: {hariult.elapsed.total_seconds():.3f} секунд")
print(f"Хэмжээ: {len(hariult.content)} байт")
print()
print("Headers:")
for tulkhuur, utga in hariult.headers.items():
print(f" {tulkhuur}: {utga}")Status code: 200
URL: https://api.open-meteo.com/v1/forecast?latitude=47.92&longitude=106.92¤t=temperature_2m
Encoding: utf-8
Хугацаа: 0.412 секунд
Хэмжээ: 398 байт
Headers:
Date: Mon, 13 Jul 2026 14:23:45 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 398
....headers — серверийн нэмэлт мэдээлэл (dictionary!).
Хамгийн чухал header нь Content-Type — тэр нь "энэ body юу вэ" гэдгийг хэлнэ. application/json гэвэл — JSON. text/html гэвэл — HTML.
.elapsed — хүсэлт хэдэн секунд болсон. Дебагт хэрэгтэй.
Эдгээрийг цээжлэх шаардлагагүй. Гэхдээ мэдэж байх нь зүйтэй.
Хэрэв сонирхвол: daily параметр нэмээд, ирэх өдрүүдийн урьдчилсан мэдээг авч үзээрэй.
python
parametruud = {
"latitude": 47.92,
"longitude": 106.92,
"daily": "temperature_2m_max,temperature_2m_min",
"timezone": "auto",
"forecast_days": 7,
}Хариултын бүтэц нь өөр байна:
python
udur_tutmiin = uguudul["daily"]
print(udur_tutmiin["time"]) # огноонуудын ЖАГСААЛТ
print(udur_tutmiin["temperature_2m_max"]) # температуруудын ЖАГСААЛТДараа нь zip -ээр (Бүлэг 2.3) тэднийг зэрэгцүүлж хэвлээрэй:
python
for ognoo, ikh, bag in zip(
udur_tutmiin["time"],
udur_tutmiin["temperature_2m_max"],
udur_tutmiin["temperature_2m_min"],
):
print(f"{ognoo}: {bag:>5.1f}°C — {ikh:>5.1f}°C")Бүлэг 2-ын zip нь API өгөгдөл дээр ажиллаж байна.
Мөн хүсвэл: өөр API-ууд туршиж үзээрэй. Жишээ нь:
python
hariult = requests.get("https://restcountries.com/v3.1/name/mongolia")Тэр нь Монгол улсын мэдээлэл (хүн ам, нийслэл, валют) буцаана.
1. ModuleNotFoundError
ModuleNotFoundError: No module named 'requests'Хэрэв
ModuleNotFoundErrorгарвал —(venv)идэвхтэй эсэхээ шалгаарай.
Дараа нь pip install requests.
2. .text -ыг ашиглаж, гараар задлах
python
tekst = hariult.text
temperatur = tekst.split('"temperature_2m":')[1].split("}")[0] # АЙМШИГТАЙХэзээ ч ингэж БҮҮ хий. .json() ашигла — тэр нь бүх ажлыг зөв хийнэ.
(Бүлэг 6.3-ын сургамжтай ижил: "CSV-г ХЭЗЭЭ Ч split(',') -ээр задалж болохгүй.")
3. URL -д параметрийг гараар угсрах
python
url = f"https://api.example.com/search?ner={ner}"Хэрэв ner -д зай, кирилл, & байвал — URL эвдэрнэ. params= ашигла.
4. Status code шалгахгүй
python
uguudul = requests.get(url).json()
print(uguudul["current"]["temperature_2m"])Хэрэв сервер 404 эсвэл 500 буцаавал — .json() нь алдаа гаргаж болно, эсвэл өөр бүтэцтэй өгөгдөл ирнэ. Дараа нь KeyError.
Энэ бол дараагийн хоёр хичээлийн сэдэв. Одоохондоо мэдэж байгаарай.
5. Loop дотор хязгааргүй хүсэлт илгээх
python
for i in range(10000):
requests.get(url)429 Too Many Requests — сервер таныг хориглоно. Болгоомжтой бай.
6. .json() -ыг JSON биш хариу дээр дуудах
Хэрэв сервер HTML буцаавал:
requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)Бүлэг 6.2-оос танил алдаа! Expecting value: line 1 column 1 — "энэ нь JSON биш байна."
Хичээл 11.5-т үүнийг зохицуулна.
pip install requests — идэвхтэй (venv) дотор. Бүлэг 1-ийн зуршил ажилд орлоо.
requests.get(url) — GET хүсэлт илгээж, Response объект буцаана.
.status_code — гурван оронтой тоо. 200 = амжилттай.
.json() — хариултын body -г PYTHON DICTIONARY болгож задална. Дотроо json.loads() дууддаг (Бүлэг 6.2).
.text — body -г string болгож өгнө. Гараар задлахыг ХЭЗЭЭ Ч бүү оролдоорой.
params= keyword argument — query parameter -ыг DICTIONARY -ээр дамжуул. requests нь URL encoding -ыг автоматаар хийнэ.
URL -д параметрийг ГАРААР бүү угсра — тусгай тэмдэгт дээр эвдэрнэ.
API-гийн хариу нь ҮҮРЛЭСЭН DICTIONARY — Бүлэг 5.3-ын БҮХ мэдлэг шууд ажиллана: uguudul["current"]["temperature_2m"].
Талбар байхгүй байж болно → .get(key) ашигла (Бүлэг 4.3), KeyError -ээс хамгаална.
ХОЁР API-г ГИНЖЛЭЖ болно — нэгний гаралт нөгөөгийн оролт.
Loop дотор API дуудахдаа БОЛГООМЖТОЙ. Олон хүсэлт → 429 Too Many Requests. Хүлээлт нэм, өгөгдлийг хадгал.
ModuleNotFoundError → (venv) идэвхтэй эсэхээ шалга.
Дараагийн хичээлд бид status code -ыг зохих ёсоор нь боловсруулна. Одоохондоо бид 200 ирнэ гэж НАЙДСАН. Гэвч бодит амьдрал дээр 404, 400, 429, 500 бүгд ирж болно.
Мөн тэнд бид үүрлэсэн JSON хариултаас өгөгдөл гаргаж авах аргыг гүнзгий үзнэ — Бүлэг 5.3-ын мэдлэг бодит API дээр бүрэн ажиллана.
Бүртгэлтэй болсноор энэ сургалтын бүх хичээлд хандах эрх авна.