asyncio.run Hatası Almadan Jupyter’da CAPTCHA Nasıl Çözülür

jupyter notebook captcha - How to Solve CAPTCHAs in Jupyter Without asyncio.run Errors

Bir Jupyter notebook’ta CAPTCHA çözmek için capskip paketini %pip ile kurun; böylece paket kernel’ın kendi Python’ına yüklenir. Ardından CapSkip’i bir hücreden, bir betikte yaptığınız gibi çağırın ya da AsyncCapSkip istemcisini doğrudan hücrenin en üst düzeyinde await edin. Yapmamanız gereken şey, async çağrıyı asyncio.run() içine sarmaktır. Kernel zaten bir event loop çalıştırır; bu yüzden asyncio.run RuntimeError yükseltir ve Playwright’ın senkron API’si de aynı nedenle başlamayı reddeder. Jupyter notebook’ta CAPTCHA çözmenin kendine özgü iki tuzağı daha vardır: durdurma düğmesi bir çözümü her zaman durduramaz ve Windows’ta eski bir ipykernel, Playwright’ın tarayıcı başlatmasını engeller. Bu rehber, ipykernel 7.4 ve 7.3 üzerinde test edilmiş olarak kurulumu, iki istemciyi, tarayıcıları ve uzak kernel’ları ele alıyor.

Neye ihtiyacınız var

  • Bir Windows makinesinde çalışan CapSkip. Örnekler reCAPTCHA v2 çözer; SDK’nın desteklediği diğer tüm türler de bir hücrede aynı şekilde çalışır.
  • Python 3.10 veya üzeri ve güncel bir capskip paketi (bu yazı yazıldığında 1.3.0); ayrıca sayfa için requests ve Beautiful Soup. Playwright yalnızca bir tarayıcıya ihtiyacınız varsa gerekir.
  • Herhangi bir biçimde Jupyter: Notebook 7, JupyterLab ya da VS Code’daki notebook düzenleyicisi. Üçü de hücrelerinizi ipykernel üzerinde çalıştırır ve aşağıdaki tüm davranışların kaynağı da budur.
  • Çözücü için bir adres. Local modu 127.0.0.1 üzerinden yalnızca o cihaza yanıt verir; Server modu ise ağ adresinizi veya genel IP’nizi dinler, böylece başka bir makinedeki bir kernel onu API üzerinden çağırabilir. İkisi de bağlantı ayarları bölümünde yer alır; Server moduna ne zaman ihtiyaç duyduğunuzu son bölüm anlatıyor.

1. Adım: %pip ile kernel’ın Python’ına kurun

Kurulumu bir notebook hücresinden, yüzde işaretiyle çalıştırın:

# pip install capskip requests beautifulsoup4, run inside the notebook:
%pip install capskip requests beautifulsoup4

Yüzde işareti önemlidir. IPython’ın %pip magic komutu pip’i kernel’ın kendi yorumlayıcısıyla, yani sys.executable ile çalıştırır; böylece paket, hücrelerinizin import yaptığı yere yüklenir. Ünlem işareti ise satırı bir kabuğa devreder ve kabuk, PATH üzerinde ilk sırada hangi pip varsa onu çalıştırır. Birden fazla Python bulunan bir makinede bunlar farklı kurulumlardır. Bir testte kernel’daki %pip capskip 1.3.0 bildirirken, global bir Python 3.14 kurulumuna ait kabuktaki pip, yeni CAPTCHA türlerini içermeyen eski 1.0.1 sürümünü bildirdi. Devam etmeden önce hangi Python’ı ve hangi sürümü aldığınızı kontrol edin:

import sys
import capskip

print(sys.executable)        # the Python this kernel runs on
print(capskip.__version__)   # 1.3.0 or later

Bir paketi yükselttiğinizde paket zaten import edilmişse, yeni sürümün yüklenmesi için kernel’ı yeniden başlatın. IPython da %pip sonrasında aynı hatırlatmayı yazdırır.

2. Adım: senkron istemciyle bir hücrede çözün

Senkron istemci bir notebook’ta özel hiçbir şeye ihtiyaç duymaz. Sayfayı bir requests.Session ile çekin, widget’ı bulun ve çözün:

import requests
from bs4 import BeautifulSoup
from capskip import CapSkip

PAGE_URL = "https://example.com/login"

# pollingInterval caps the wait between polls. At 1 instead of the
# default 5, the stop button takes effect within about a second.
solver = CapSkip(host="127.0.0.1", port=8080, pollingInterval=1)

session = requests.Session()
page = session.get(PAGE_URL, timeout=30)
soup = BeautifulSoup(page.text, "html.parser")
widget = soup.select_one(".g-recaptcha[data-sitekey]")
form = widget.find_parent("form")

token = solver.recaptcha(sitekey=widget["data-sitekey"], url=PAGE_URL)["code"]
len(token)

Ardından token’ı bir sonraki hücrede, formun kendi alanları ve aynı oturumla gönderin:

from urllib.parse import urljoin

def form_fields(form):
    """The fields a browser would send: hidden, text and checked boxes."""
    fields = {}
    for tag in form.select("input[name]"):
        kind = (tag.get("type") or "text").lower()
        if kind in ("submit", "button", "image", "file", "reset"):
            continue
        if kind in ("checkbox", "radio") and not tag.has_attr("checked"):
            continue
        fields[tag["name"]] = tag.get("value", "on" if kind in ("checkbox", "radio") else "")
    return fields

data = form_fields(form)
data["username"] = "YOUR_USERNAME"
data["g-recaptcha-response"] = token
res = session.post(urljoin(PAGE_URL, form.get("action") or PAGE_URL), data=data,
                   headers={"Referer": PAGE_URL}, timeout=30)
res.status_code

Oturum, sayfanın çerezlerini gönderime taşır; gizli CSRF alanını ziyaretinize bağlayan da budur. Referer başlığı, bir tarayıcının göndereceği başlığın yerini tutar: requests hiç göndermez ve aralarında Django’nun da bulunduğu bazı framework’ler, Referer veya Origin içermeyen bir HTTPS form gönderimini reddeder. Bir reCAPTCHA token’ı tek bir gönderim için ve yaklaşık iki dakika geçerlidir; bu yüzden gönderim hücresini daha sonra dönmek yerine çözüm hücresinin hemen ardından çalıştırın.

Bir notebook’un bir betikten ayrıldığı yer durdurma düğmesidir. Bir kesme isteği (interrupt) hücrenizde KeyboardInterrupt yükseltir, ancak bir Windows kernel’ında bu istek yalnızca o anki çağrı döndüğünde işlenir. SDK bir çözümün çoğunu yoklamalar arasında uyuyarak geçirir; bu yüzden hücre bu bekleme bittiğinde durur: varsayılan pollingInterval ile en fazla beş saniye, yukarıdaki ayarla yaklaşık bir saniye sonra. Traceback tuhaf görünür: önce bir NetworkException, ardından onu işlerken yükseltilen KeyboardInterrupt gelir. O NetworkException, SDK’nın hazır değil sinyalinden başka bir şey değildir.

Kötü durum, bağlantıyı kabul edip hiç yanıt vermeyen bir CapSkip’tir. Senkron istemci HTTP çağrılarında hiçbir zaman aşımı ayarlamaz; bu yüzden Windows’ta hücre, hiçbir kesme isteğinin ulaşamadığı bir soket okumasında takılı kalır. recaptchaTimeout da işe yaramaz, çünkü SDK onu yalnızca yoklamalar arasında kontrol eder. Kernel’ı yeniden başlatmak hücreyi serbest bırakır ama tüm değişkenleri kaybettirir. CapSkip’i kapatmak da hücreyi serbest bırakır ve değişkenleri korur, çünkü kopan bağlantı okumayı sonlandırır ve daha önce gönderdiğiniz kesme isteği anında işlenir. Ayrıca yarıda kesmek CapSkip’i değil, yalnızca hücrenizi durdurur: SDK’da bir işi iptal edecek bir çağrı yoktur; dolayısıyla terk edilen çözüm devam eder ve token’ı hiçbir zaman okunmaz.

3. Adım: bir hücrede async kullanımı: üst düzeyde await edin, asla asyncio.run kullanmayın

Bir betikten async kod çalıştırmanın olağan yolu bir notebook’ta başarısız olur:

import asyncio
from capskip import AsyncCapSkip

asolver = AsyncCapSkip(host="127.0.0.1", port=8080, pollingInterval=1)

asyncio.run(asolver.recaptcha(sitekey=widget["data-sitekey"], url=PAGE_URL))
# RuntimeError: asyncio.run() cannot be called from a running event loop

ipykernel her hücreyi daha önce başlattığı bir event loop içinde çalıştırır, asyncio.run ise yeni bir tane başlatmakta ısrar eder. Daha eski kalıp olan asyncio.get_event_loop().run_until_complete() de RuntimeError: This event loop is already running hatasıyla başarısız olur. İki çağrı da CapSkip’e hiç ulaşmaz, dolayısıyla hiçbir iş gönderilmez. Verdiğiniz coroutine hiç çalışmaz; bu yüzden sonraki bir hücre, onun hiç await edilmediğini söyleyen bir RuntimeWarning yazdırabilir. Bu uyarı zararsızdır. Çaresi, sorunun kendisinden daha basittir. IPython, herhangi bir fonksiyonun dışında, hücrenin en üst düzeyinde await kullanmanıza izin verir:

# No asyncio.run: the kernel's loop runs this await.
from capskip import AsyncCapSkip

asolver = AsyncCapSkip(host="127.0.0.1", port=8080, pollingInterval=1)
result = await asolver.recaptcha(sitekey=widget["data-sitekey"], url=PAGE_URL)
token = result["code"]

Bu da AsyncCapSkip’i, üslubun ötesinde iki nedenle notebook için daha iyi istemci yapar. Bir kesme isteği await’i hemen iptal eder, dolayısıyla hücre bir sonraki yoklamayı beklemeden anında sona erer. Ayrıca HTTP çağrıları, sessiz bir bağlantıdan varsayılan olarak beş saniye sonra vazgeçen httpx üzerinden gider. Bu durumda yanıt vermeyi bırakan bir CapSkip karşısında çağrı askıda kalmak yerine bir SDK hatasıyla sona erer: bir yoklama takılırsa recaptchaTimeout dolduktan kısa süre sonra TimeoutException, gönderim takılırsa beş saniye sonra NetworkException. Durdurma düğmesi bu süre boyunca çalışmaya devam eder. Bu bekleme süresini kısaltmak için recaptchaTimeout değerini constructor’da ayarlayın; Python SDK’sında recaptcha() hiçbir timeout argümanı almaz ve bir tane vermek TypeError yükseltir.

Aynı anda birden fazla çözüm için tek bir gather yeterlidir. CapSkip varsayılan olarak reCAPTCHA’yı 10 thread üzerinde çözer (ayarlarındaki Max. Threads değeri) ve bunların arkasında kuyruğa giren bir görev, CapSkip onu başarısız saymadan önce en fazla 250 saniye bekler; bu yüzden kümeyi sınırlayın:

import asyncio

# Max. Threads for reCAPTCHA is 10 by default; more than that queues.
limit = asyncio.Semaphore(10)

async def solve(sitekey, url):
    async with limit:
        return (await asolver.recaptcha(sitekey=sitekey, url=url))["code"]

# jobs: (sitekey, url) pairs; here the Step 2 page three times
jobs = [(widget["data-sitekey"], PAGE_URL)] * 3
tokens = await asyncio.gather(*(solve(k, u) for k, u in jobs), return_exceptions=True)

gather tüm token’ları en sonda birlikte döndürür; bu yüzden onları hemen gönderin ya da asyncio.as_completed kullanıp her birini geldiği anda gönderin. return_exceptions=True ile başarısız bir çözüm, hücreden dışarı fırlamak yerine listede kendi istisnası olarak döner; bu yüzden yalnızca dize olan girdileri gönderin. Bir kümedeki çözümler tek bir CapSkip makinesini paylaşır, dolayısıyla her birinin tek başına bir çözümden daha yavaş çalışmasını bekleyin. İstemci ayrıca her yoklama için yeni bir HTTP istemcisi oluşturur ve bu, Windows’ta her seferinde kernel’ın yaklaşık onda bir saniyelik CPU zamanını harcar; dolayısıyla büyük bir küme bir CPU çekirdeğini meşgul tutar. Daha büyük kümeler için kalıplar şurada: Python’da paralel CAPTCHA çözme rehberi.

asyncio.run hatasına verilen eski yanıtlar nest_asyncio önerir. Kullanmayın. Proje Mart 2024’te arşivlendi. Python 3.14’te onu uygulamak kernel’ı bozar: bir sonraki hücreden itibaren, siz yeniden başlatana kadar AsyncCapSkip dahil her httpx çağrısı, bir NoneType nesnesine yönelik zayıf referansla ilgili bir TypeError ile başarısız olur. Üst düzey await hiçbir yamaya ihtiyaç duymaz.

4. Adım: notebook içinde bir tarayıcı

Selenium’un kendine ait bir event loop’u yoktur; bu yüzden bir webdriver oturumu bir hücrede, tıpkı bir betikte olduğu gibi çalışır: 2. adımdaki senkron istemciyle çözün ve token’ı sayfaya yazın. Playwright’ın senkron API’si çalışan bir loop olup olmadığını kontrol eder ve şu hatayla reddeder: Error: It looks like you are using Playwright Sync API inside the asyncio loop. Please use the Async API instead. Bu yüzden bir notebook’ta Playwright’ı, üst düzeyde await kullanarak async API’si üzerinden yönetirsiniz:

# pip install playwright into the kernel, then download a browser once:
%pip install playwright
import sys
!"{sys.executable}" -m playwright install chromium
from playwright.async_api import async_playwright

# start() instead of "async with", so the browser outlives this cell.
pw = await async_playwright().start()
browser = await pw.chromium.launch()
page = await browser.new_page()
await page.goto(PAGE_URL)

sitekey = await page.locator(".g-recaptcha").get_attribute("data-sitekey")
token = (await asolver.recaptcha(sitekey=sitekey, url=page.url))["code"]

# The widget's hidden textarea is the field the form submits.
await page.locator("#g-recaptcha-response").evaluate("(el, t) => { el.value = t; }", token)
await page.locator("form button[type=submit]").click()

pw ve browser nesnelerini değişkenlerde tutmak, sonraki hücrelerden sayfayı kurcalamanıza olanak tanır; bir notebook’un asıl amacı da büyük ölçüde budur. İşiniz bittiğinde ikisini de await browser.close() ve await pw.stop() ile kapatın. Kernel’ın kendi sys.executable yorumlayıcısını çağırmak, %pip ile aynı nedenle, tarayıcıyı hücrelerinizin import ettiği Playwright ile eşleştirir. Tırnaklar boşluk içeren bir yolu bozulmadan korur, ünlem işaretli satır ise indirme ilerlemesini hücrede gösterir. Tarayıcıyı yönetmenin kendisiyle ilgili daha fazlası Playwright CAPTCHA çözücü rehberinde.

Windows üzerinde Playwright’ta hata ayıklamaya başlamadan önce ipykernel sürümünüzü kontrol edin. 7.3 sürümüne kadar ipykernel orada hücreleri bir selector event loop üzerinde çalıştırıyordu; bu loop asyncio alt süreçlerini başlatamaz, bu yüzden chromium.launch() çıplak bir NotImplementedError ile başarısız olur. Eylül 2026 sonunda yayımlanan 7.4.0 sürümü, Windows hücrelerini Proactor loop’una taşıdı ve aynı hücre çalışır hâle geldi. Hangisine sahip olduğunuzu görmek için ipykernel.__version__ değerini yazdırın. Yükseltmek için notebook’ta %pip install -U ipykernel komutunu çalıştırın ve kernel’ı yeniden başlatın. Yükseltemiyorsanız bir worker thread işe yaramaz, çünkü selector politikası tüm kernel sürecini kapsar. Bunun yerine tarayıcıyı, chromedriver’ı asyncio olmadan başlatan Selenium ile yönetin.

Kernel bilgisayarınızda değilse: Server modu

Yukarıdaki her şey, kernel’ın CapSkip ile aynı makinede çalıştığını, dolayısıyla 127.0.0.1’in ona ulaştığını varsayar. Jupyter notebook’ta CAPTCHA çözmek için olağan kurulum budur, ama tek kurulum değildir. Bir sunucuda JupyterHub tarafından sunulan bir notebook, VS Code’daki uzak bir kernel ya da Google Colab gibi barındırılan bir notebook, hücrelerinizi başka bir yerde çalıştırır ve orada 127.0.0.1 o makine anlamına gelir. Bu durumda ilk çağrı, reddedilen bir bağlantıyla birlikte NetworkException ile başarısız olur. Bağlantı ayarlarından CapSkip’i Server moduna alın; o zaman ağ adresinizi veya genel IP’nizi dinler, böylece uzak kernel onu aynı API üzerinden, host olarak bu adresi kullanarak çağırır.

Rota internetten geçiyorsa statik bir genel IP kullanın. CapSkip, Server modu başladığında portunu her adrese açar; bu yüzden erişimi beklediğiniz makinelerle sınırlamak için diğerlerine yönelik bir Windows Firewall engelleme kuralı ekleyin. Bu yöntem, kendi JupyterHub sunucunuzda olduğu gibi kernel’ın adresi sabit olduğunda işe yarar. Barındırılan bir notebook’un giden adresi ise oturumdan oturuma değişebilir; bu yüzden orada CapSkip’in ayarlarında API anahtarı doğrulamasını açın ve anahtarı apiKey olarak verin. Donanım yine sizin donanımınızdır ve çözüm başına ücretlendirme yine yoktur. İstemci ortam değişkenlerini kendiliğinden okumaz; bu yüzden, tam örnekte olduğu gibi, CAPSKIP_HOST değerini bir hücrede os.getenv ile okuyup istemciye verin.

Tam çalışan örnek

Üç hücre, baştan sona async: durdurma düğmesine dayanıklı, Jupyter notebook’ta CAPTCHA çözmenin en kısa eksiksiz iş akışı.

# Cell 1: pip install capskip requests beautifulsoup4, then restart the kernel.
%pip install capskip requests beautifulsoup4
# Cell 2: the client and a helper. Run once per kernel.
import os
from urllib.parse import urljoin

import requests
from bs4 import BeautifulSoup
from capskip import AsyncCapSkip, CapSkipError

PAGE_URL = "https://example.com/login"
solver = AsyncCapSkip(
    apiKey=os.getenv("CAPSKIP_API_KEY", "capskip"),
    host=os.getenv("CAPSKIP_HOST", "127.0.0.1"),
    port=int(os.getenv("CAPSKIP_PORT", "8080")),
    pollingInterval=1,
)

def form_fields(form):
    fields = {}
    for tag in form.select("input[name]"):
        kind = (tag.get("type") or "text").lower()
        if kind in ("submit", "button", "image", "file", "reset"):
            continue
        if kind in ("checkbox", "radio") and not tag.has_attr("checked"):
            continue
        fields[tag["name"]] = tag.get("value", "on" if kind in ("checkbox", "radio") else "")
    return fields
# Cell 3: fetch, solve, post. Run it again for a fresh token.
session = requests.Session()
page = session.get(PAGE_URL, timeout=30)
soup = BeautifulSoup(page.text, "html.parser")
widget = soup.select_one(".g-recaptcha[data-sitekey]")
if widget is None:
    raise RuntimeError("No reCAPTCHA widget in the HTML; the page may build it with JavaScript.")
form = widget.find_parent("form")

try:
    result = await solver.recaptcha(sitekey=widget["data-sitekey"], url=PAGE_URL)
except CapSkipError as err:
    raise RuntimeError(f"solve failed: {type(err).__name__}: {err}") from err

data = form_fields(form)
data["username"] = "YOUR_USERNAME"
data["g-recaptcha-response"] = result["code"]
res = session.post(urljoin(PAGE_URL, form.get("action") or PAGE_URL), data=data,
                   headers={"Referer": PAGE_URL}, timeout=30)
print(res.status_code)

3. hücre, yeniden çalıştırdığınız hücredir ve her çalıştırma yeni bir çözüm ve yeni bir token demektir, çünkü bir reCAPTCHA token’ı yalnızca bir kez çalışır. Sayfa widget’ını JavaScript ile oluşturuyorsa çekilen HTML’de sitekey bulunmaz; bunun yerine 4. adımdaki Playwright hücrelerini kullanın ya da sitekey’i widget’ı oluşturan script’ten okuyun.

Sık görülen hatalar ve anlamları

GördüğünüzNedenDüzeltme
RuntimeError: asyncio.run() cannot be called from a running event loopKernel zaten bir event loop çalıştırıyorÇağrıyı hücrenin en üst düzeyinde await edin
RuntimeError: This event loop is already runningrun_until_complete, kernel’ın kendi loop’u üzerinde çağrıldıÇağrıyı hücrenin en üst düzeyinde await edin
Playwright, asyncio loop’u içinde Sync API kullandığınızı söylüyorSenkron API, bir loop çalışırken çalışmayı reddederawait ile playwright.async_api kullanın; ipykernel 7.4 veya üzerinde senkron kodu bir worker thread’inde çalıştırmak da işe yarar
Windows’ta chromium.launch() kaynaklı NotImplementedError7.4.0 öncesi ipykernel hücreleri, tarayıcı sürecini başlatamayan bir selector loop üzerinde çalıştırır%pip install -U ipykernel komutunu çalıştırın, ardından kernel’ı yeniden başlatın
capskip için ModuleNotFoundError ya da kurduğunuzdan daha eski bir sürümKabuktaki pip, kernel’ınkinden farklı bir Python’a kurulum yaptı%pip ile kurun ve sys.executable değerini kontrol edin
Durdurma düğmesi hiçbir şey yapmıyor ve hücre çalışmaya devam ediyorSenkron istemci, bağlantıyı kabul edip hiç yanıt vermeyen bir CapSkip’i bekliyor ve hiçbir HTTP zaman aşımı ayarlamıyorCapSkip’i kapatın ya da kernel’ı yeniden başlatın; notebook’larda AsyncCapSkip’i tercih edin
Python 3.14’te her httpx veya AsyncCapSkip çağrısında zayıf referansla ilgili bir TypeErrornest_asyncio önceki bir hücrede uygulandıKernel’ı yeniden başlatın ve nest_asyncio kullanmayı bırakın; üst düzey await hiçbir yamaya ihtiyaç duymaz
Reddedilen bir bağlantıyla NetworkExceptionCapSkip çalışmıyor ya da kernel başka bir makinede çalışıyorCapSkip’i başlatın ya da Server moduna alıp adresini istemciye verin
ERROR_CAPTCHA_UNSOLVABLE içeren ApiExceptionCapSkip çözümü başarısız saydı, örneğin boş bir thread için 250 saniye bekledikten sonraKümeleri Max. Threads değerinde tutun, proxy ekleyin, ardından yeniden deneyin
Site, CapSkip’in döndürdüğü bir token’ı reddediyorGönderim, sayfanın çerezleri, gizli alanları ya da bir Referer olmadan yapıldı veya token iki dakikadan eskiydiÇözümün hemen ardından aynı requests.Session üzerinden, form_fields ve bir Referer ile gönderin

FAQ

Bu, JupyterLab ve VS Code notebook’larında çalışır mı?

Evet. JupyterLab, Notebook 7 ve VS Code’daki notebook düzenleyicisi hücrelerinizi ipykernel üzerinde çalıştırır; bu yüzden üst düzey await, asyncio.run hatası ve Windows event loop’u her birinde aynı davranır. Farklı olan, kernel’ın hangi Python’ı kullandığıdır; bu yüzden hangi düzenleyiciyi açarsanız açın sys.executable değerini kontrol edin.

Google Colab gibi barındırılan bir notebook, bilgisayarımdaki çözücüyü kullanabilir mi?

Evet, Server modu sayesinde. Barındırılan bir notebook kernel’ını sağlayıcının makinelerinde çalıştırır; dolayısıyla oradaki 127.0.0.1 sizin bilgisayarınız değildir. Bağlantı ayarlarından CapSkip’i Server moduna alın, bilgisayara statik bir genel IP verin, API anahtarı doğrulamasını açın ve adresinizi ve anahtarınızı istemciye verin. Barındırılan bir notebook’un giden adresi değişebilir; bu yüzden yabancıları dışarıda tutan şey anahtardır. Yine de bir Windows Firewall engelleme kuralı, portu hiç kullanmadığınız adres aralıklarına kapatabilir. Çözücü sizin sahip olduğunuz donanımda kalır, dolayısıyla uzun bir yeniden çalıştırma oturumu ödediğiniz tutarı asla değiştirmez.

asyncio.run çalışsın diye nest_asyncio kullanmalı mıyım?

Hayır. nest_asyncio çalışan loop’u yamalar; böylece asyncio.run onun içinde iç içe çalışabilir. Bu, bu hata için yaygın bir çözümdü. Proje arşivlendi ve Python 3.14’te bu yama, AsyncCapSkip dahil kernel’daki sonraki her httpx çağrısını bozar. Üst düzey await, loop ile ilgili hiçbir şeyi değiştirmeden asyncio.run çağrısından beklediğiniz şeyi zaten yapar.

Bir hücreyi yarıda kestiğimde çözüme ne olur?

Hücreniz durur, CapSkip ise devam eder. SDK’da bir işi iptal edecek bir çağrı yoktur; bu yüzden CapSkip çözümü tamamlar ve token’ı kimse okumaz. Hücreyi yeniden çalıştırmak yeni bir iş gönderir. Büyük bir kümeyi yarıda keserseniz terk edilen çözümler, her biri bitene ya da CapSkip’in kendi zaman aşımlarına takılana kadar CapSkip’in thread’lerini meşgul tutar. Bu dakikalar sürebilir; dolayısıyla hemen başlatılan yeni bir küme onların arkasında bekler.

Kısa özet

Jupyter notebook’ta CAPTCHA çözmek beş alışkanlığa dayanır. %pip ile kurun, asla kabuk üzerinden kurmayın. Senkron CapSkip istemcisi bir hücrede, bir betikte olduğu gibi çalışır; kesme istekleri hızlı işlensin diye pollingInterval değerini 1 yapın. Async için AsyncCapSkip’i hücrenin en üst düzeyinde await edin; onu asla asyncio.run içine sarmayın, nest_asyncio kullanmaya da kalkışmayın. Tarayıcı için Selenium’u olduğu gibi ya da Playwright’ın async API’sini kullanın ve Windows’ta ipykernel 7.4 veya üzerini çalıştırın. Kernel başka bir makinede çalışıyorsa CapSkip’i Server moduna alın ve adresini istemciye verin.

Notebook, bir scraper’ın her yeniden çalıştırmada biraz daha şekillendiği yerdir. Kendi makinenizde çalışan bir captcha atlatma aracıyla bu yeniden çalıştırmaların her biri ücretsiz olur.