वेब स्क्रैपिंग: ब्राउज़र टीएलएस फिंगरप्रिंट नकल
Senior Web Scraping Engineer
TL;DR:
- rnet एक असिंक्रोनस HTTP क्लाइंट है जो एक वास्तविक ब्राउज़र के TLS फिंगरप्रिंट की नकल करता है, इसलिए जब एक सर्वर हैंडशेक को प्रोफाइल करता है, तो उसे Chrome दिखाई देता है, न कि Python डिफ़ॉल्ट। यह Rust पर आधारित है और Python को एक्सपोज़ किया गया है।
- rnet क्या नहीं करता है, वह है JavaScript को रेंडर करना। एक पूर्ण फिंगरप्रिंट अनुरोध को स्वीकार कराता है; यह उन स्क्रिप्टों को निष्पादित नहीं करता जो एक पृष्ठ की सामग्री बनाते हैं।
- इस गाइड में फिंगरप्रिंट वास्तविक है। Chrome के रूप में नकल करते हुए एक सक्रिय रन ने HTTP/2 पर एक ब्राउज़र के आकार का JA3 और
t13d1516h2JA4 उत्पन्न किया - और फिर भी एक स्क्रिप्ट-बिल्ट पृष्ठ पर 0 कोट ब्लॉक मिले। - rnet वह क्लाइंट भी है जो Scrapeless को कॉल करता है। वही असिंक्रोनस क्लाइंट Scrapeless यूनिवर्सल स्क्रैपिंग API को URL POST करता है, रेंडर की गई HTML प्राप्त करता है, और सभी 10 लेखकों को खींचता है।
- दो अलग-अलग समस्याएँ, स्पष्ट रूप से विभाजित। rnet TLS-फिंगरप्रिंट परत को संभालता है; Scrapeless रेंडरिंग को संभालता है। कोई भी दूसरे का स्थान नहीं लेता।
- फेच साइड पर शुरू करने के लिए स्वतंत्र। app.scrapeless.com पर अपनी Scrapeless API कुंजी बनाएं।
rnet क्या है, और क्या नहीं है
rnet एक असिंक्रोनस HTTP क्लाइंट है जो Python के लिए Rust के नेटवर्किंग स्टैक पर बनाया गया है, और इसकी विशिष्ट विशेषता TLS और HTTP फिंगरप्रिंट की नकल करना है। जब एक क्लाइंट एक TLS कनेक्शन खोलता है, तब उसके हैंडशेक का सटीक आकार - सिफर ऑर्डर, एक्सटेंशन, कर्व - एक फिंगरप्रिंट बनाता है जिसे सर्वर प्रोफाइल कर सकते हैं; एक मानक Python क्लाइंट का फिंगरप्रिंट ऐसा होता है जो कोई ब्राउज़र उत्पन्न नहीं करता, और कुछ साइटें इसे एक भी बाइट HTML सर्व किए बिना अस्वीकार कर देती हैं। rnet एक चयनित ब्राउज़र के हैंडशेक को फिर से बनाता है, इसलिए कनेक्शन Chrome या Firefox के रूप में पढ़ा जाता है, और यह HTTP/2 पर एक असिंक्रोनस API के साथ करता है।
जो यह नहीं है वह एक रेंडरर है। एक मिलान करने वाला फिंगरप्रिंट आपको हैंडशेक-स्तरीय प्रोफाइलिंग से आगे ले जाता है; यह JavaScript के बारे में कुछ नहीं करता। पृष्ठ अपनी सामग्री को स्क्रिप्टों के माध्यम से बनाता है, और rnet, किसी भी HTTP क्लाइंट की तरह, सर्वर द्वारा भेजा गया मार्कअप लौटाता है - जो एक स्क्रिप्ट-बिल्ट पृष्ठ पर सामग्री के बिना होता है। इसलिए, एक rnet स्क्रैपर दो समस्याओं को अलग करता है जो अक्सर भ्रमित होती हैं: फिंगरप्रिंट परत, जहां rnet अपनी जगह बनाता है, और रेंडरिंग परत, जिसके लिए एक ब्राउज़र की आवश्यकता होती है। यह गाइड रेंडरिंग के लिए Scrapeless यूनिवर्सल स्क्रैपिंग API का उपयोग करती है, जिसमें rnet कॉल करता है। व्यापक चित्र के लिए, Python वेब स्क्रैपिंग ट्यूटोरियल साथी है।
इंस्टाल करें
rnet इस गाइड के लिए संपूर्ण टूलचेन है। जिस संस्करण के खिलाफ इसे लिखा गया था वह rnet 2.4.2 है:
bash
pip install "rnet==2.4.2"
अपनी कुंजी को पर्यावरण में रखें, स्रोत में कभी नहीं:
bash
export SCRAPELESS_API_KEY="sk_your_scrapeless_key"
एक ब्राउज़र की नकल करें, और देखें कि यह कहाँ रुकता है
rnet को एक फिंगरप्रिंटिंग एंडपॉइंट पर एक ब्राउज़र नकल सेट के साथ निर्देशित करें, और हैंडशेक उस ब्राउज़र के रूप में पढ़ा जाता है। JA3 और JA4 TLS हैंडशेक का मानक संक्षिप्त विवरण हैं - फिंगरप्रिंट जो TLS 1.3 मानक के तहत बातचीत की गई है - और rnet ब्राउज़र के आकार के मान उत्पन्न करता है। फिर भी, वही क्लाइंट एक स्क्रिप्ट-बिल्ट पृष्ठ पर कुछ नहीं पाता है, क्योंकि फिंगरप्रिंट का क्लाइंट-साइड रेंडरिंग पर कोई प्रभाव नहीं पड़ता है जो पृष्ठ को भरता है:
python
# fingerprint.py — एक वास्तविक ब्राउज़र हैंडशेक, और इसकी सीमा
import asyncio
import json
import re
import rnet
FINGERPRINT_URL = "https://tls.peet.ws/api/all"
PAGE_URL = "https://quotes.toscrape.com/js/"
async def main() -> None:
client = rnet.Client(impersonate=rnet.Impersonate.Chrome131)
resp = await client.get(FINGERPRINT_URL)
fp = json.loads(await resp.text())
ja3 = fp.get("tls", {}).get("ja3_hash", "")
ja4 = fp.get("tls", {}).get("ja4", "")
print("ja3 is 32-hex:", bool(re.fullmatch(r"[0-9a-f]{32}", ja3)))
print("ja4 prefix:", ja4.split("_")[0])
print("http version:", fp.get("http_version"))
page_resp = await client.get(PAGE_URL)
page = await page_resp.text()
print("js-page quote blocks:", page.count('class="quote"'))
asyncio.run(main())
हैंडशेक ब्राउज़र के आकार का है; पृष्ठ अभी भी खाली है:
text
ja3 is 32-hex: True
ja4 prefix: t13d1516h2
http version: h2
js-page quote blocks: 0
JA3 हैश डिज़ाइन द्वारा रन से रन भिन्न होता है - ब्राउज़र एक एक्सटेंशन के तहत GREASE तंत्र को यादृच्छिक बनाते हैं, और rnet इसे फिर से बनाता है - इसलिए एक स्क्रैपर आकार की जांच करता है, एक निश्चित मान नहीं। JA4 प्रीफिक्स t13d1516h2 स्थिर भाग है: TLS 1.3, 16 सिफर सूट, 16 एक्सटेंशन, HTTP/2। जो भी नहीं करता, वह पृष्ठ को रेंडर करना है।
Scrapeless के साथ रेंडर करें, जिसे rnet द्वारा कॉल किया गया
एक ही आसिंक्रोनस क्लाइंट को बनाए रखें और लक्ष्य बदलें: Scrapeless यूनिवर्सल स्क्रैपिंग एपीआई के लिए POST URL, जो सर्वर-साइड पर रेंडर करता है और समाप्त HTML लौटाता है। rnet इस अनुरोध को अन्य किसी अनुरोध की तरह संभालता है, इसलिए एक क्लाइंट दोनों फिंगरप्रिंट-संवेदनशील फेच और रेंडर किए गए फेच को कवर करता है:
python
# rendered.py — rnet रेंडर एपीआई को कॉल करता है, फिर निकालता है
import asyncio
import json
import os
import re
import rnet
async def main() -> None:
client = rnet.Client(impersonate=rnet.Impersonate.Chrome131)
resp = await client.post(
"https://api.scrapeless.com/api/v2/unlocker/request",
headers={"x-api-token": os.environ["SCRAPELESS_API_KEY"], "Content-Type": "application/json"},
json={"actor": "unlocker.webunlocker", "input": {"url": "https://quotes.toscrape.com/js/", "js_render": True}},
)
html = json.loads(await resp.text())["data"]
authors = re.findall(r'<small class="author">(.*?)</small>', html)
print("रेंडर किए गए उद्धरण ब्लॉक:", html.count('class="quote"'))
print("पहला लेखक:", authors[0])
asyncio.run(main())
अब सामग्री मौजूद है:
text
रेंडर किए गए उद्धरण ब्लॉक: 10
पहला लेखक: अल्बर्ट आइंस्टीन
यह पूरा स्क्रैपर है, और यह पूरी प्रक्रिया में rnet के अंदर रहा: आसिंक्रोनस क्लाइंट जो एक ब्राउज़र फिंगरप्रिंट को ले जाता है, रेंडर कॉल भी करता है। यूनिवर्सल स्क्रैपिंग एपीआई रेंडरिंग करता है; rnet HTTP करता है।
अपनी एपीआई कुंजी मुफ्त योजना पर प्राप्त करें: app.scrapeless.com
उन्नत पैटर्न
- नकलीकरण को वर्तमान ब्राउज़र से मेल करें।
rnet.Impersonateविशिष्ट ब्राउज़र संस्करणों को उजागर करता है; एक हाल के संस्करण का चयन करें, चूंकि वर्षों पुराने निर्माण का फिंगरप्रिंट एक संकेत है। क्लाइंट का एपीआई लक्ष्य के साथ नहीं बदलता। - एक क्लाइंट का पुन: उपयोग करें। एक
rnet.Clientकनेक्शन को पूल करता है; इसे एक बार बनाएं और इसे एक आसिंक्रोनस टास्क समूह में साझा करें न कि प्रति अनुरोध, जहां आसिंक्रोनस ट्रांसपोर्ट लाभदायक होता है। - आकार की जांच करें, मूल्य की नहीं। क्योंकि GREASE हर कनेक्शन पर JA3 को यादृच्छिक बनाता है, पहले स्क्रिप्ट की तरह 32-हैक्स पैटर्न और JA4 प्रीफिक्स पर जोर दें — कभी भी एक हार्ड-कोडेड हैश नहीं।
- जब आकार बढ़ता है तो एक पार्सर जोड़ें। रेग्युलर एक्सप्रेशन इसे एक निर्भरता पर रखता है; छंटनी के लिए रेंडर किए गए HTML को एक चयनकर्ता पुस्तकालय में फीड करें और वहाँ फ़ील्ड चुनें।
समस्या निवारण
- एक साइट अभी भी अनुरोध को ब्लॉक करती है। एक TLS फिंगरप्रिंट एक संकेत है जो कि बहुत से संकेतों में से एक है। यदि एक ब्राउज़र के आकार का हैंडशेक पर्याप्त नहीं है, तो ब्लॉक परिवहन के ऊपर है — IP प्रतिष्ठा, हेडर, या एक चुनौती — और अनुरोध Scrapeless पथ पर है, जो इनको संभालता है।
- एक पृष्ठ से शून्य ब्लॉक्स जो आप ब्राउज़र में देख सकते हैं। सामग्री जावास्क्रिप्ट द्वारा रेंडर की गई है; फिंगरप्रिंट ने अनुरोध को स्वीकार करने में मदद की लेकिन स्क्रिप्ट कभी नहीं चलीं। उस URL को Scrapeless कॉल के माध्यम से
js_renderके साथ रूट करें। - हर रन में JA3 हैश बदलता है। यह सही है — GREASE इसे यादृच्छिक बनाता है, ठीक वैसे ही जैसे एक असली ब्राउज़र करता है। इसके बजाय पैटर्न और JA4 प्रीफिक्स पर जोर दें।
- प्रतिक्रिया पर
awaitत्रुटियाँ। rnet आसिंक्रोनस है: अनुरोध और.text()को पढ़ना दोनों ही अपेक्षित हैं, और सब कुछasyncio.runके भीतर चलता है, जैसा कि उदाहरणों में दिखाया गया है।
निष्कर्ष
rnet अपने स्थान को इस परत के रूप में अर्जित करता है जो हैंडशेक को सही दिखाता है: एक आसिंक्रोनस, Rust-समर्थित क्लाइंट जो एक असली ब्राउज़र का TLS फिंगरप्रिंट ले जाता है, और जो रेंडर कॉल भी करता है। वह समस्या जो यह हल नहीं करता है, वह पृष्ठ स्वयं है — फिंगरप्रिंट स्क्रिप्ट के शून्य-ब्लॉक्स परिणाम ने इसे तय किया — और rnet द्वारा भेजा गया एक Scrapeless POST उस अंतर को बंद करता है। फिंगरप्रिंट परत और रेंडरिंग परत को एक ही क्लाइंट में डालें और डेमो पृष्ठ के दस लेखक जुड़ेगा जिसे सर्वर Chrome के रूप में पढ़ता है।
एक मुफ्त Scrapeless खाता बनाएं एपीआई कुंजी प्राप्त करने के लिए, और डेवलपर दस्तावेज़ unlocker.webunlocker पैरामीटर को कवर करते हैं। जब आप एक आवर्ती नौकरी की योजना बनाते हैं तो Scrapeless मूल्य निर्धारण देखें।
सामान्य प्रश्न
प्रश्न: क्या rnet स्वयं जावास्क्रिप्ट-रेंडर किए गए पृष्ठों को स्क्रैप कर सकता है?
नहीं। rnet एक HTTP क्लाइंट है जिसमें फिंगरप्रिंट नकलीकरण है; यह TLS परत पर एक अनुरोध को स्वीकार करता है लेकिन कोई जावास्क्रिप्ट नहीं चलाता। एक स्क्रिप्ट-निर्मित पृष्ठ पर फेच मार्कअप के साथ सामग्री के बिना लौटाता है — गाइड का शून्य-ब्लॉक्स परिणाम। उन पृष्ठों को Scrapeless यूनिवर्सल स्क्रैपिंग एपीआई के माध्यम से रूट करें, जो उन्हें रेंडर करता है, rnet कॉल करता है।
प्रश्न: TLS फिंगरप्रिंट नकलीकरण वास्तव में क्या करता है?
यह rnet के TLS हाथ मिलाने को एक चुने हुए ब्राउज़र के अनुसार आकार देता है, ताकि एक सर्वर जो JA3 या JA4 फ़िंगरप्रिंट की प्रोफाइलिंग कर रहा है, वह एक सामान्य Python क्लाइंट के बजाय Chrome या Firefox देख सके। यह हैंडशेक-स्तरीय फ़िल्टरिंग को स्पष्ट करता है; यह आईपी-आधारित अवरोध, चुनौती पृष्ठों, या JavaScript को लागू करने की आवश्यकता को स्पष्ट नहीं करता है।
प्रश्न: rnet, curl_cffi से कैसे अलग है?
दोनों ब्राउज़र फ़िंगरप्रिंट का अनुकरण करते हैं। rnet Rust पर आधारित है और पहले से ही असिंक्रोनस है; curl_cffi curl-impersonate को लपेटता है और समकालिक है। अपने स्क्रैपर के असिंक्रोनस होने और आपको किस अनुकरण लक्ष्य की आवश्यकता है, इसके आधार पर चुनें - दोनों-स्तरीय पैटर्न एक ही तरीके से है।
प्रश्न: JA3 हैश हर रन पर क्यों बदलता है?
क्योंकि असली ब्राउज़र एक TLS एक्सटेंशन को GREASE तंत्र के माध्यम से यादृच्छिक करते हैं, और rnet उस व्यवहार की नकल करता है। एक निश्चित JA3 खुद कृत्रिम दिखेगा। एक विशिष्ट मान के बजाय 32-हैक्स पैटर्न और JA4 उपसर्ग की जांच करें।
प्रश्न: क्या rnet के साथ स्क्रैपिंग कानूनी है?
HTTP क्लाइंट संग्रहण नियमों को नहीं बदलता है। केवल सार्वजनिक पृष्ठों को लाएँ, साइट की शर्तों और रोबोट्स निष exclusionन प्रोटोकॉल द्वारा मानकीकृत रोबोट निर्देशों का सम्मान करें, मात्रा सीमित रखें, और किसी भी व्यक्तिगत डेटा को आपके लिए लागू होने वाले कानूनों के तहत संभालें।
स्क्रैपलेस में, हम केवल सार्वजनिक रूप से उपलब्ध डेटा का उपयोग करते हैं, जबकि लागू कानूनों, विनियमों और वेबसाइट गोपनीयता नीतियों का सख्ती से अनुपालन करते हैं। इस ब्लॉग में सामग्री केवल प्रदर्शन उद्देश्यों के लिए है और इसमें कोई अवैध या उल्लंघन करने वाली गतिविधियों को शामिल नहीं किया गया है। हम इस ब्लॉग या तृतीय-पक्ष लिंक से जानकारी के उपयोग के लिए सभी देयता को कोई गारंटी नहीं देते हैं और सभी देयता का खुलासा करते हैं। किसी भी स्क्रैपिंग गतिविधियों में संलग्न होने से पहले, अपने कानूनी सलाहकार से परामर्श करें और लक्ष्य वेबसाइट की सेवा की शर्तों की समीक्षा करें या आवश्यक अनुमतियाँ प्राप्त करें।



