Bir Python Scraper'da cf_clearance Çerezleri Nasıl Yeniden Kullanılır

cf_clearance cookie - How to Reuse cf_clearance Cookies in a Python Scraper

Cloudflare challenge'ını çözmek işin yalnızca yarısıdır. Onu çözdüğünüzde elde ettiğiniz şey bir cf_clearance çerezidir ve sonraki isteğin yeniden challenge'a maruz kalmasını asıl engelleyen şey bu çerezdir. Hızla süresi dolar, çoğu insanın beklediğinden daha fazla şeye bağlıdır ve istemciniz onu kazanan istemciden uzaklaştığı anda çalışmayı durdurur. Bu yazı, çerezin ne olduğunu, nasıl yakalanacağını, neyin onu sessizce geçersiz kıldığını ve süresi dolmuş olanı bozuk olandan nasıl ayırt edeceğinizi ele alır.

Neye ihtiyacınız var

  • Python 3.10 veya daha yenisi, session destekli bir HTTP istemcisiyle. Örnekler, çerezlerin istekler arasında kalıcı olması için bir session kullanır.
  • Gerçekten bir challenge veren bir hedef. Sizi hiç challenge'a maruz bırakmayan bir site, çerezi asla ayarlamaz; bu yüzden test edilecek hiçbir şey olmaz.
  • CapSkip çalışıyor olmalı; ister loopback adresinde Local modda, ister worker'larınızın erişebileceği bir makinede Server modda. Her ikisi de bağlantı ayarları. O yüzden başlamadan önce birini seçin.

cf_clearance çerezi aslında nedir

Bu bir makbuzdur. Cloudflare referansı bunu şöyle tanımlar: bu çerez geçilen challenge'ın kanıtını saklar, ve çerez mevcut olduğunda artık bir challenge verilmemesi için kullanılır. Aynı zamanda JavaScript tespitlerinin saklandığı çerezdir ve durumun siteler arası isteklerde hayatta kalması için SameSite None, Secure ve Partitioned olarak ayarlanır.

Yaşam süresi sizin seçiminiz değildir. Erişmeye çalıştığınız sitedeki Challenge Passage ayarından gelir ve Cloudflare varsayılanı açıkça belgeliyor: cf_clearance çerezinin yaşam süresi 30 dakikadır ve makul aralık olarak 15 ile 45 dakika arası önerilir. Bazı siteler bunu kısaltır. Bazıları uzatır. Değeri dışarıdan okuyamazsınız; bu yüzden her clearance'ı kısa ömürlü sayın ve süresinin uzun sürmesini ummak yerine yenileme için tasarlayın.

Bundan üç pratik sonuç çıkar. Çerezi saklamalısınız, çünkü her istekte yeniden çözmek yavaş ve savurgandır. Bir yeniden başlatmayı atlatacağını asla varsaymamalısınız. Ve çerezin bayatladığını fark edip sessizce yenisini kazanan bir kod yolunuz olmalıdır.

Adım 1: challenge'ı çözün, ardından istemcinin tamamını saklayın

Öncelikle kaçınmaya değer hata, token'ı ödül gibi görmektir. Değildir. Bir Turnstile challenge'ını çözerek elde ettiğiniz token, clearance karşılığında takas ettiğiniz şeydir ve geri aldığınız çerez, sonrasında değeri olan şeydir. Dolayısıyla sıra: çöz, gönder, ardından yanıtı alan session'ı elinizde tutun.

# pip install capskip
from capskip import CapSkip

solver = CapSkip(host="127.0.0.1", port=8080)

# A challenge page needs two more values than a plain widget does.
result = solver.turnstile(
    sitekey="YOUR_SITEKEY",
    url="https://example.com/protected",
    data="YOUR_CDATA",
    pagedata="YOUR_CHLPAGEDATA",
)

token = result["code"]
agent = result["userAgent"]   # not optional, see the next section

O token'ı, sayfanın kendisinin yapacağı şekilde, saklamayı düşündüğünüz bir session'dan gönderin. Yanıt geri geldiğinde, clearance çerezi o session'ın cookie jar'ında bulunur ve doğrudan okuyabilirsiniz.

# pip install requests
import requests

s = requests.Session()
s.headers["User-Agent"] = agent      # the exact agent the solver returned

# ... submit the token here, exactly as the challenge page does ...

clearance = s.cookies.get("cf_clearance")
print(bool(clearance))               # True once the challenge is cleared

Adım 2: neyin onu sessizce geçersiz kıldığını bilin

Cloudflare tam bağlamayı yayımlamaz; bu yüzden bu tablo belgelenmiş bir sözleşmeden ziyade gözlemlenmiş davranıştır. Üzerine inşa edilecek kadar tutarlıdır ve buradaki her satır birine bir öğleden sonrasına mal olmuştur.

Ne değiştiClearance hayatta kalır mıNeden
User agent dizenizHayırClearance, belirli bir tarayıcı kimliğine verilmişti
Kaynak IP adresinizHayırYeni bir adrese giden bir çerez, klasik tekrar oynatma (replay) imzasıdır
TLS parmak izinizGenellikle hayırEl sıkışma çerezden önce okunur, bu yüzden bir uyumsuzluk daha erken yakalanır
Gönderdiğiniz ana bilgisayar adı (hostname)HayırClearance site başınadır, hesap başına veya ağ başına değil
Zamanın geçmesiYalnızca Challenge Passage süresi dolana kadarVarsayılan 30 dakikadır ve site bunu değiştirebilir
İlgisiz çerezler eklemekEvetDiğer çerezler clearance kontrolü tarafından yok sayılır

İlk üç satır, tek bir kuralın üç farklı kılığa girmiş halidir: clearance bir istemciye aittir, size değil. Bu yüzden onu kazanan kimliği sabitleyin. Bu, o çerezin tüm ömrü boyunca tek bir user agent, tek bir çıkış IP'si ve tek bir TLS profili anlamına gelir. Session ortasında bir proxy'yi değiştirmek, zaten ödediğiniz clearance'ı çöpe atar; bu, çalışan bir scraper'ın görünürde hiçbir neden yokken yeniden challenge almaya başlamasının en yaygın tek yoludur.

Bu, aynı zamanda çözücünün yalnızca bir token değil, bir user agent da geri döndürmesinin nedenidir. Turnstile, token'ı onu üreten tarayıcı kimliğine bağlar; bu yüzden farklı bir agent altında gönderilen bir token, kendisi tamamen geçerli olsa bile reddedilir. Döndürülen değeri olduğu gibi kullanın ve ortaya çıkan çerezi taşıyan her istekte kullanmaya devam edin. Turnstile challenge sayfası anlatımı iki ekstra girdi değerinin nereden geldiğini gösterir; bu da insanların yanlış yaptığı diğer yarısıdır.

Adım 3: çalıştırmalar arasında kalıcı hale getirin

Süreciniz sona erdiğinde ölen bir clearance çerezi, bir yeniden başlatmayı atlatan bir çerezden çok daha az değerlidir. Cookie jar'ı, ona eşlik eden kimlikle birlikte saklayın; çünkü çerez tek başına, farklı bir agent veya farklı bir proxy altında yeniden yüklerseniz işe yaramaz.

# pip install requests
import json, time

def save_clearance(session, agent, proxy, path="clearance.json"):
    """Store the cookie with the identity that earned it."""
    blob = {
        "cf_clearance": session.cookies.get("cf_clearance"),
        "user_agent": agent,
        "proxy": proxy,
        "stored_at": time.time(),
    }
    with open(path, "w") as fh:
        json.dump(blob, fh)

Yeniden yükleme, bir ekstra kontrolle birlikte bunun ayna görüntüsüdür. Challenge almayı beklemek yerine kaydı kendiniz yaşlandırıp devre dışı bırakın; çünkü proaktif bir yenileme bir çözüme mal olurken, reaktif bir yenileme önce başarısız bir isteğe mal olur.

# pip install requests
import json, time, requests

def load_clearance(path="clearance.json", max_age=900):
    """Return a ready session, or None if the record is too old."""
    with open(path) as fh:
        blob = json.load(fh)

    # 15 minutes, comfortably inside a 30 minute default.
    if time.time() - blob["stored_at"] > max_age:
        return None

    s = requests.Session()
    s.headers["User-Agent"] = blob["user_agent"]
    s.proxies = {"https": blob["proxy"]} if blob["proxy"] else {}
    s.cookies.set("cf_clearance", blob["cf_clearance"])
    return s

On beş dakika, kasıtlı olarak muhafazakar bir tavan değeridir. Bir sitenin yapılandırdığı Challenge Passage değerini göremezsiniz, varsayılan 30 dakikadır ve yarı yolda yenilemek bozuk bir yığın yerine ucuz bir çözüme mal olur. Çözücü kendi donanımınızda ve çözüm başına ücret olmadan çalışıyorsa, erken davranmak bedavadır.

Adım 4: bayat bir clearance'ı tahmin etmeden tespit edin

Ölü bir clearance kendini temiz bir hatayla duyurmaz. Genellikle normal görünen bir 403 ya da istediğiniz JSON yerine bir HTML ara sayfası (interstitial) taşıyan bir 200 alırsınız. Yalnızca durum kodunu kontrol etmek ikinci durumu yakalamaz ve yalnızca durum kodlarını izleyen bir yeniden deneme döngüsü, bunun üzerinde mutlu mutlu sonsuza dek döner.

# pip install requests
def needs_new_clearance(response):
    """True when this response is a challenge rather than content."""
    if response.status_code in (403, 503):
        return True
    body = response.text[:4000].lower()
    markers = ("cf-turnstile", "challenge-platform", "just a moment")
    return any(m in body for m in markers)

Bunu ayrıştırıcınızın önüne bağlayın, arkasına değil. True döndürdüğünde saklanan kaydı atın, bir kez çözün ve taze session ile yeniden deneyin. Eski çerezle ve daha uzun bir sleep ile yeniden denemeyin, çünkü onda yanlış olan şey zaman değildir. Aynı ayrım reCAPTCHA token'larında da karşımıza çıkar, üstelik orada süresi dolma penceresi daha da kısadır; bir reCAPTCHA token'ının ne kadar süre geçerli kaldığı üzerine yazı bunun o tarafını ele alır.

Çözücüyü onun yerine bir sunucuda çalıştırmak

Clearance çerezleri kimlik başınadır; bu yüzden bir worker filosu, bir clearance filosuna ihtiyaç duyar ve bunların her birinin çözülmesi gerekir. Bu işin worker üzerinde gerçekleşmesi şart değildir. Bağlantı ayarları her iki düzenlemeyi de kapsar:

ModDinlediği adresNe zaman kullanılır
Yerel127.0.0.1, yalnızca o cihazScraper'ınız ve çözücü aynı makinede çalışıyor
SunucuAğ adresiniz veya genel IP'nizWorker'lar, bir VPS veya barındırılan bir platform API üzerinden çağrı yapar

SDK host'unu çözücü makineye yönlendirin, kodunuzda başka hiçbir şey değişmez; böylece her biri kendi cookie jar'ını tutarken yirmi worker tek bir örneği paylaşabilir. Çağrı yapanlar kendi ağınızın dışında bulunduğunda statik bir genel IP önerilir. Ayrıntılar bağlantı ayarları altında bulunur; Server mode yine sizin donanımınızdır ve yine ölçümsüzdür (unmetered): yalnızca çözücünün nerede çalıştığını değiştirir, kime ait olduğunu asla değiştirmez.

FAQ

Bir cf_clearance çerezi ne kadar süre dayanır?

Varsayılan olarak otuz dakika ve site sahibi bunu değiştirebilir. Cloudflare bunu Challenge Passage ayarı olarak sunar ve 15 ile 45 dakika arasında tutulmasını önerir; bu yüzden karşılaştığınız çoğu site bu aralığın bir yerinde olacaktır. Yapılandırılan değeri dışarıdan okuyamazsınız; bu da kontrol ettiğiniz bir zamanlayıcıyla yenilemenin, yeniden challenge almayı beklemekten neden daha iyi olduğunu açıklar.

Birden fazla worker arasında tek bir clearance çerezi paylaşabilir miyim?

Yalnızca onu kazanan kimliği paylaşıyorlarsa; bu da pratikte aynı çıkış IP'si, aynı user agent ve aynı TLS profili anlamına gelir. Bu, tek bir proxy'nin arkasında başarılabilir ve çözümlerden tasarruf etmenin iyi bir yoludur. İki worker farklı çıkış adresleri kullandığı anda, paylaşılan çerez bunlardan biri için başarısız olmaya başlar ve hangi worker'a düştüklerini fark edene kadar başarısızlıklar rastgele görünür.

Proxy'leri döndürdükten sonra clearance'ım neden çalışmayı durdurdu?

Çünkü clearance eski adrese verilmişti. Yeni bir IP'den gelen bir çerez, tekrar oynatma (replay) korumasının yakalamak için var olduğu tam da bu kalıptır; bu yüzden atılır ve yeniden challenge alırsınız. Bunun yerine session sınırında döndürün: bir proxy bir clearance kazanır, süresi dolana kadar onu kullanır ve bir sonraki session yeni bir adres ve yeni bir çözümle baştan başlar.

Bir clearance çerezini tutmak için gerçek bir tarayıcıya ihtiyacım var mı?

Hayır. Etrafındaki kimlik sabit kaldığı sürece, bir cookie jar'ı olan herhangi bir HTTP istemcisi onu taşıyabilir. Bir tarayıcının size bedavaya verdiği şey inandırıcı bir TLS el sıkışması ve inandırıcı bir başlık sırasıdır; sade bir HTTP istemcisinde ise varsayılan olarak ikisi de yoktur. Yani zor olan kısım çerez değil, tutarlılıktır ve taklit eden bir istemci, bir tarayıcının bellek maliyeti olmadan bunu karşılar.

En kısa hâli

cf_clearance çerezini, tek bir istemciye bağlı kısa ömürlü bir makbuz olarak ele alın. Onu challenge'ı geçen session'dan yakalayın, onu kazanan user agent ve proxy ile birlikte saklayın ve engellenmeyi beklemek yerine yaklaşık on beş dakikalık bir zamanlayıcıyla yenileyin. Yalnızca durum koduna değil, gövdeye de bakın; çünkü bir challenge tamamen sağlıklı bir 200 ile gelir. Süresi dolduğunda, tek bir taze çözüm tüm çözümdür ve bir captcha çözücü , kendi donanımınızda çalıştığında bunu erken yapmaya yetecek kadar ucuzlaştırır. Bir Turnstile çözümünün alabileceği iki girdi şekli için, Cloudflare Turnstile çözücü sayfasını herhangi bir şeyi bağlamadan önce okuyun. Worker havuzu bağlantısı ayrıca web scraping için CAPTCHA çözücü altında ele alınır; birden fazla worker çalıştırıyorsanız yirmi dakikaya değer.