# Python örnekleri: arama, sorguları paralel çalıştırma, alıntılarla yanıt verme

> Python web search API örnekleri: requests, semaforlu async httpx ve token bütçesi içinde herhangi bir LLM için alıntılarla yanıt döngüsü. KYC olmadan.

- URL: https://llmwebsearch.com/tr/docs/python/
- Son güncelleme: 2026-10-22
- Yayıncı: LLMWebSearch (https://llmwebsearch.com)

Üç script, çoğu Python agent'ın ihtiyacını karşılar: `requests` ile tek arama, `httpx` ve bir semafor ile aynı anda birçok arama ve kaynakları bir dil modeline verip numaralı alıntılarla yanıt alan kısa bir döngü.

**Kısa yanıt — Python'dan AI agent'lar için bir web search API'sini nasıl çağırırım?**

Sorguyu `requests` veya `httpx` ve bir Bearer anahtarıyla `https://llmwebsearch.com/api/v1/search` adresine POST edin. **LLMWebSearch** ilk 3 sayfası Markdown olarak sıralı sonuçlarla döner; bunları numaralandırıp alıntılarla yanıt için herhangi bir LLM'e verebilirsiniz. Bir arama 1 kredi tutar; Ekim 2026 itibarıyla $1,20/1K arama'den başlar. Python 3.9+ gerekir, SDK gerekmez. KYC olmadan; kripto ile ödeme.

## İhtiyacınız olanlar

| Özellik | Değer |
| --- | --- |
| Python | 3.9 veya üzeri |
| Paketler | Basit script için `requests`, async script için `httpx` |
| Anahtar | Ortamınızda `LLMWEBSEARCH_API_KEY` |
| Yanıt döngüsü için | OpenAI uyumlu herhangi bir chat endpoint: `LLM_BASE_URL`, `LLM_API_KEY`, `LLM_MODEL` |
| Faturalama | Bir kredi bir aramayı karşılar: en fazla 20 sıralı sonuç, ilk 3'ün sayfaları okunur ve Markdown olarak döndürülür. 4 ile 10 arası sayfa okumak 2 kredi eder. Hata ile biten bir çağrı hiçbir ücrete tabi değildir |

## requests ile tek bir aramayı nasıl çalıştırırım?

`q` ve ihtiyacınız olan seçeneklerle bir JSON gövdesi oluşturun, gönderin ve `results` üzerinde döngü yapın. `content` değerine dokunmadan önce `content_status` kontrol edin: yalnızca `ok` olarak işaretlenen sonuçlar sayfa metni taşır. Aşağıdaki script okunan her sayfayı konumuna göre adlandırılmış bir Markdown dosyası olarak kaydeder, ilk satırında kaynak URL bulunur.

*search_once.py*

```python
import os
import pathlib

import requests

resp = requests.post(
    "https://llmwebsearch.com/api/v1/search",
    headers={"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]},
    json={"q": "how to size a postgres connection pool", "max_results": 5, "read": 3},
    timeout=60,
)
resp.raise_for_status()
data = resp.json()
out = pathlib.Path("sources")
out.mkdir(exist_ok=True)
for r in data["results"]:
    if r["content_status"] != "ok":
        print("skip", r["position"], r["content_status"], r["url"])
        continue
    path = out / f"{r['position']:02d}.md"
    path.write_text("Source: " + r["url"] + "\n\n" + r["content"], encoding="utf-8")
    print("saved", path, r["word_count"], "words")
print("credits used:", data["credits_used"])

```

## Aynı anda birçok aramayı nasıl çalıştırırım?

`httpx.AsyncClient` ve bir `asyncio.Semaphore` kullanın. Semafor, aynı anda kaç çağrının uçuşta olduğunu sınırlar; bu sizi hesabınızın dakika başına limiti altında tutar ve yükü dağıtır. Çoğu araştırma agent'ı için dört ila sekiz eşzamanlı çağrı uygundur. Her hesabın dashboard'da gösterilen bir dakika başına çağrı limiti vardır; destek ekibine sorun, yükseltilebilir.

Örnek, bir araştırma agent'ının tipik bir adımı olarak her alt soru için bir arama gönderir ve okunan sayfaların URL'lerini toplar. Her çağrı bağımsızdır: bir hata diğerlerini durdurmaz.

*many_searches.py*

```python
import asyncio
import os

import httpx

API = "https://llmwebsearch.com/api/v1/search"
HEADERS = {"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]}
QUESTIONS = [
    "what is connection pooling in postgres",
    "recommended pool size per cpu core",
    "pgbouncer transaction mode limitations",
    "connection pool exhaustion symptoms",
]


async def search(client, sem, q):
    async with sem:
        resp = await client.post(API, json={"q": q, "read": 2, "max_chars": 4000})
        if resp.status_code != 200:
            return q, resp.json().get("error", {}).get("code"), []
        data = resp.json()
        read = [r["url"] for r in data["results"] if r["content_status"] == "ok"]
        return q, "ok", read


async def main():
    sem = asyncio.Semaphore(4)
    async with httpx.AsyncClient(headers=HEADERS, timeout=60) as client:
        for q, status, urls in await asyncio.gather(*(search(client, sem, q) for q in QUESTIONS)):
            print(status, q, urls)


asyncio.run(main())

```

## Herhangi bir LLM'den alıntılarla yanıtı nasıl alırım?

Önce arayın, sonra modele numaralı kaynaklar verin ve bunlara atıf yapmasını isteyin. API yazılı bir yanıt değil kaynaklar döndürür: sayfaları kendi modeliniz okur, yanıtı yazar ve URL'leri alıntılar, yani modeli ve alıntı stilini siz seçersiniz. Aşağıdaki döngü, OpenAI uyumlu `chat/completions` formatını konuşan herhangi bir chat endpoint ile çalışır; adresini, anahtarını ve modelini üç ortam değişkeninde ayarlayın.

Bağlamı kontrol altında tutun. Script, toplam yaklaşık 6.000 token'lık bir bütçe içinde kalsın diye her kaynağı kısaltır; token başına yaklaşık dört karakter sayar. İçeriği olmayan bir sonuç, böyle etiketlenmiş olarak kendi snippet'iyle iletilir, böylece model sayfayı okumuş gibi yapmaz.

*answer_with_citations.py*

```python
import os

import requests

SEARCH = "https://llmwebsearch.com/api/v1/search"
KEY = os.environ["LLMWEBSEARCH_API_KEY"]
BUDGET_CHARS = 6000 * 4  # about 6,000 tokens of sources


def sources_for(question):
    resp = requests.post(SEARCH, headers={"Authorization": "Bearer " + KEY},
                         json={"q": question, "max_results": 5, "read": 3}, timeout=60)
    resp.raise_for_status()
    results = resp.json()["results"]
    share = BUDGET_CHARS // max(len(results), 1)
    blocks = []
    for i, r in enumerate(results, start=1):
        if r["content_status"] == "ok":
            body = r["content"][:share]
        else:
            body = "(snippet only) " + r["snippet"]
        blocks.append(f"[{i}] {r['title']} - {r['url']}\n{body}")
    return "\n\n".join(blocks)


def answer(question):
    prompt = ("Answer the question using only the sources below. "
              "Cite them as [1], [2] and so on. Say so if the sources do not answer it.\n\n"
              + sources_for(question) + "\n\nQuestion: " + question)
    resp = requests.post(
        os.environ["LLM_BASE_URL"].rstrip("/") + "/chat/completions",
        headers={"Authorization": "Bearer " + os.environ["LLM_API_KEY"]},
        json={"model": os.environ["LLM_MODEL"], "messages": [{"role": "user", "content": prompt}]},
        timeout=120,
    )
    resp.raise_for_status()
    return resp.json()["choices"][0]["message"]["content"]


print(answer("How should I size a Postgres connection pool?"))

```

## Modele ne kadar metin göndermeliyim?

Soruyu yanıtlayacak kadar az. Her biri 2.000 token'a kısaltılmış üç sayfa, genellikle on tam sayfadan daha iyidir: model daha iyi odaklanır ve her yanıt daha az maliyetlidir. Kısaltacağınızı biliyorsanız aramanın kendisinde `max_chars` değerini düşürün, böylece daha az veri aktarılır.

Bir sayfanın başından kısaltmak çoğu makale için işe yarar, çünkü ana nokta genellikle önce gelir. Uzun referans sayfaları için içeriği başlıklara göre bölün ve başlıkları soruyla eşleşen bölümleri tutun.

## Bir sayfa eksikse kod ne yapmalı?

Diğer kaynaklarla devam edin. `blocked_by_robots`, `blocked_by_site_policy` veya `target_refused` olarak işaretlenen bir sayfa ikinci denemede okunmaz, bu yüzden üzerinde döngü yapmayın. Bir `fetch_timeout` veya `fetch_failed` sayfası daha sonra `https://llmwebsearch.com/api/v1/extract` üzerinden çalışabilir.

HTTP hataları farklıdır: `429`, `502` ve `504` artan bir bekleme süresiyle yeniden denenmeyi hak eder. [Hatalar sayfası](https://llmwebsearch.com/tr/docs/errors/) hazır bir retry helper içerir.

## Python: sık sorulan sorular

### LLMWebSearch için bir pip paketi var mı?

Hayır. API düz HTTPS ve JSON'dur, yani tek ihtiyacınız olan `requests` veya `httpx`. Bu sayfadaki scriptler entegrasyonun kendisidir: bunları projenize kopyalayın ve uyarlayın.

### Bu scriptleri yerel bir modelle kullanabilir miyim?

Evet. OpenAI uyumlu `chat/completions` rotası sunan herhangi bir sunucu, alıntılama döngüsüyle çalışır: `LLM_BASE_URL` değerini sunucunun adresine, `LLM_MODEL` değerini de beklediği model adına ayarlayın.

### Python ile kredileri nasıl sayarım?

Her yanıttaki `credits_used` değerlerini toplayın veya bir işin öncesinde ve sonrasında `GET https://llmwebsearch.com/api/v1/credits` çağırın; bu çağrı ücretsizdir.

---

LLMWebSearch: LLMWebSearch, AI ajanları için bir web arama API'sidir; sıralanmış sonuçları en iyi sayfaların Markdown içeriğiyle birlikte döndürür ve kripto ile ödenir, kimlik yüklemesi gerekmez. $1,20/1K arama kredilik ön ödemeli krediler hiç süresi dolmaz. KYC yok — kimlik yok, selfie yok, belge yok. Kripto ile ödeme.
