Cloudflare ve tarayıcı otomasyonu
Closed this issue · 3 comments
(I don't know what your preferred language is, but I will continue in Turkish anyway, as the target audience is Turkish people.)
Merhaba 👋,
Öncelikle, tarayıcı otomasyonları, oldukça kullanışlı ve güçlü olmalarına karşın, düz HTTP isteklerine kıyasla yavaşlar, pratik ve "taşınabilir" değiller (taşınabilirlikten kastım, birkaç KB'lık kod dosyası için yüzlerce MB'lık tarayıcı kullanmak), ve bundan dolayı, mümkün oldukça tarayıcı gereksiniminin kaldırılması taraftayım.
Tarayıcı otomasyonuna ihtiyacınız olduğunun farkındayım, çünkü belli ki bunu Cloudflare'i aşmak için kullanıyorsunuz, fakat Cloudflare'i aşmanın tek yolu bu değil, bu yüzden bilgilendirmek amacıyla bu konuyu açıyorum.
Cloudflare, (daha doğrusu TürkAnime'nin Cloudflare'i ayarlayış şekli ile) curl
kullanarak sitenin kaynağına erişilmesine izin veriyor, yani yönlendirme ve Cloudflare'in "bağlantınız kontrol ediliyor" sayfası olmadan.
$ curl -s https://www.turkanime.co | tidy --show-warnings no -q | grep \<title\>
<title>Türk Anime TV | Türkçe Altyazılı Anime izle</title>
Aynı şeyi herhangi bir HTTP kütüphanesi ile deneyecek olursak, (httpx
gibi) tahmin edildiği gibi, sayfanın kendi kaynağı yerine Cloudflare sayfasına ulaşıyoruz.
$ python -c "import httpx; print(httpx.get('https://www.turkanime.co').text)" | tidy --show-warnings no -q | grep \<title\>
<title>Just a moment...</title>
curl
'un gönderdiği üst başlıkları ("header") sadece Python'da oluşturarak Cloudflare'i aşmak mümkün değil, çünkü Cloudflare sadece üst başlıklara değil, bağlantının özelliklerine (TLS, HTTP sürümü) de bakıyor. Fakat bu, Python üzerinden bunu yapamayacağımız anlamına gelmiyor. libcurl
kütüphanesini sisteme ve pycurl
paketini de Python ortamına kurarak (veya alternatifi), ardından Python'da curl
'u çağırarak, Cloudflare'i aşmak mümkün hale gelir.
# python -m pip install pycurl==7.45.2
#
# "libcurl" sistem kütüphanesi de gerekiyor:
# sudo apt install libcurl4-openssl-dev
from pycurl import Curl, URL, WRITEDATA, CAINFO, HTTPHEADER
import certifi
from io import BytesIO
def send_request(url : str):
curl = Curl()
buffer = BytesIO()
curl.setopt(URL, "https://turkanime.co" + url)
curl.setopt(WRITEDATA, buffer)
curl.setopt(CAINFO, certifi.where())
curl.setopt(HTTPHEADER, ["User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0"])
curl.perform()
curl.close()
return buffer.getvalue().decode("utf-8")
page = send_request("https://www.turkanime.co")
Pull request açarak katkıda bulunmak isterdim ancak çeşitli sebeplerden ötürü (ve aynı zamanda kod stilinizi bozmak istemediğimden, çünkü tarayıcının ortadan kaldırıması kodda büyük çaplı bir değişiklik yapacak) şimdilik sadece bu konuyu açarak katkıda bulunabiliyorum.
Öncelikle yazın için çok teşekkürler.
Dürüst olmak gerekirse ben de genel olarak selenium kullanmaktan nefret ediyorum, kodunu balonlaştırıyor, hantallaştırıyor ve taşınabilirliğini azaltıyor. Ayrıca kulağa tembelce geliyor. Evet, curl ile sayfanın içeriğine ulaşılıyor ve bir miktar efor ile bunu python'a implemente etmek kolay.
Sıkıntı şu ki türkanime moderasyonu kafasına göre cloudflare'in "i am under the attack" modunu açıyor, en azından scripti ilk yarattığımız zamanlarda böyleydi. Cloudflare'in bu anti-bot modu bilindiği üzere client'a bir takım javascript challenge'ları çözdürerek ve 5 saniye bekleterek, duruma göre captcha göstererek onun insan olduğunu doğruluyor ve bunu http talepleriyle çözmek cidden çok zor. Github'ta bunları bypasslayan pek çok modül geliştirildi yıllardan bu yana, ama hem maintain edilmiyorlar hem de cloudflare aktif olarak kendi sistemini güncelliyor. Şuan curl versiyonunu implemente etsek gelecekte yine "IAUM"un tekrar aktifleştirileceğini bilemediğimden bir süredir bu fikiri rafa kaldırmıştım.
Akabinde selenium'un hafif çalışması için elimden geleni de yaptım açıkçası. Selenium'un bu scriptteki tek vazifesi turkanime.net/kullanici/anonim sayfasını ziyaret ederek her türlü cloudflare korumasını aşıp gerekli çerezleri yaratıp javascript paketlerini indirmekten ibaret. Script'in kalanı yalnızca javascript'de ajax.get talepleri ile devam ediyor ve datayı regex kullanarak parse'lıyor, dolayısıyla açılış sonrası süreçte oldukça hızlı. Yalnızca butonlara tıklayıp navigasyon sağlasaydık o zaman selenium kullanmanın hiçbir anlamı zaten kalmazdı.
Yine de hala aklımın bir kenarında ana metod olarak direk http talepleri kullanıp selenium'u da bir fallback opsiyonu olarak kullanmak var.
Öncelikle yazın için çok teşekkürler.
Rica ederim, ben de cevabınız için teşekkür ederim!
Sıkıntı şu ki türkanime moderasyonu kafasına göre cloudflare'in "i am under the attack" modunu açıyor, en azından scripti ilk yarattığımız zamanlarda böyleydi.
Kendilerinin durumu nasıl ele aldığını bilmiyordum, TürkAnime'nin kendisi ve işleyişi hakkında pek bilgi sahibi değilim. Durum buysa sıkıntı.
Github'ta bunları bypasslayan pek çok modül geliştirildi yıllardan bu yana, ama hem maintain edilmiyorlar hem de cloudflare aktif olarak kendi sistemini güncelliyor.
Cloudflare'in sürekli olarak sistemlerini güncellemesi doğru, ancak şurada cloudscraper
adında bir Python modülü bulunuyor, ve şu anda en güncel 1.2.68 sürümü 10 Ocak 2023 tarihinde yayınlanmış. Kendim henüz denemediğim için bir yorumda bulunamam elbette, ancak, gereksinimlerinde sadece requests'i gördüğümden geçici bir yöntem bile olsa şans vermeye değer olacağını düşünüyorum.
Script'in kalanı yalnızca javascript'de ajax.get talepleri ile devam ediyor ve datayı regex kullanarak parse'lıyor, dolayısıyla açılış sonrası süreçte oldukça hızlı. Yalnızca butonlara tıklayıp navigasyon sağlasaydık o zaman selenium kullanmanın hiçbir anlamı zaten kalmazdı.
Projenizin direkt bir kullanıcısı değilim. Kullandığınız embed linkindeki şifrelemeyi kaldırmayı Python'a uyarlamak isteyişim ile bu repoya denk geldim, o yüzden "açılış sonrası hızı" gibi konular hakkında bir yorum yapmam doğru olmaz, zaten kasıtlı olarak yavaş yapmaya çalışmadığınız ortada. "Hız" konusunda genel olarak HTTP kütüphaneleri ve tarayıcı otomasyonları arasında konuşmuştum, yoksa kötü bir kod ile HTTP kütüphaneleri kullanarak tarayıcı otomasyonlarından da yavaş çalışan bir uygulama yapılabilirdi.
cloudscraper
benim de zamanında ilk denediğim paket bu oldu, fakat:
>>> scraper = cloudscraper.create_scraper()
>>> r = scraper.get("http://turkanime.co/anime/non-non-biyori")
cloudscraper.exceptions.CloudflareChallengeError: Detected a Cloudflare version 2 Captcha challenge, This feature is not available in the opensource (free) version.
hız konusunda genel olarak HTTP kütüphaneleri ve tarayıcı otomasyonları arasında konuşmuştum
ben bu konuda sana kesinlikle katılıyorum, webdriver'lar harbiden de en son çözüm olmalı.
Bu arada embed şifresini pythona cryptodome kullanarak implemente ettiğin gist için eline sağlık, ilerde bir şekilde proje webdriver'dan kurtulursa lazım olacak.