एक्सेसिबिलिटी ट्री एक सस्ता पृष्ठ नहीं है: एजेंट्स द्वारा पढ़े जाने वाले मापना
Expert Network Defense Engineer
TL;DR:
- पहुँच वृक्ष वह है जिसे अधिकांश ब्राउज़र एजेंट अपने मॉडल को कच्चे HTML के बजाय फीड करते हैं, जो
Accessibility.getFullAXTreeके माध्यम से Chrome DevTools प्रोटोकॉल पर प्राप्त किया जाता है। - यह नहीं एक पृष्ठ का संकुचन है। एक लाइव कैटलॉग पृष्ठ पर: कच्चा HTML 9,824 टोकन,
innerText582, पूर्ण पहुँच वृक्ष 5,951 — वृक्ष की लागत 10.2× सामान्य पाठ है। - कारण नोड भूमिकाओं में स्पष्ट है: 1,401 नोड्स में से, 267
StaticTextहैं और 391InlineTextBoxहैं, इसलिए अधिकांश स्ट्रिंग्स को दो बार संग्रहित किया जाता है। - इंटरएक्टिव भूमिकाओं पर फ़िल्टरिंग करते हुए 114 नोड्स में 742 टोकन — 1.3×
innerTextमिलते हैं — जबकि हर चीज को बनाए रखते हुए जिस पर एजेंट क्लिक कर सकता है। - स्थानीय क्रोमियम और स्क्रेपलेस स्क्रैपिंग ब्राउज़र के माध्यम से मापी गई, हर संख्या एक जैसी थी, इसलिए एजेंट के पृष्ठ का प्रतिनिधित्व पर्यावरणों के बीच नहीं बदलता।
- स्क्रेपलेस का निःशुल्क योजना इस गाइड में क्लाउड-ब्राउज़र चलने को कवर करता है।
हर ब्राउज़र एजेंट को एक सवाल का जवाब देना होता है इससे पहले कि वह कुछ कर सके: आप मॉडल को क्या देते हैं? एक 51,004-चरित्र HTML दस्तावेज़ एक उचित प्रॉम्प्ट बजट में नहीं आता, और एक स्क्रीनशॉट छवि टोकन की कीमत चुकाता है और सटीक स्ट्रिंग्स खो देता है। सामान्य तीसरा उत्तर पहुँच वृक्ष होता है।
वह उत्तर आकार में सही और कीमत में गलत है। वृक्ष भूमिकाओं और नामों को ले जाता है — link, button, heading — जो कि बिलकुल वही है जो एक एजेंट को क्लिक करने के स्थान का निर्णय लेने के लिए चाहिए। यह भी, बिना फ़िल्टर किए, पृष्ठ के सामान्य पाठ की तुलना में एक श्रेणी अधिक महंगा है।
यह गाइड CDP के माध्यम से वृक्ष को खींचता है, इसे उसी लाइव पृष्ठ पर विकल्पों के खिलाफ मापता है, और वह फ़िल्टर दिखाता है जो इसे भेजने के योग्य बनाता है।
पहुँच वृक्ष क्या है
ब्राउज़र DOM के साथ एक दूसरा वृक्ष बनाता है, स्क्रीन रीडर्स के लिए। प्रत्येक नोड एक role ले जाता है — नियंत्रण प्रकारों में से एक जिसे WAI-ARIA विशिष्टता द्वारा परिभाषित किया गया है — और एक name, वह स्ट्रिंग जो एक स्क्रीन रीडर घोषित करता है, जो सुविधाजनक नाम और विवरण गणना में एल्गोरिदम द्वारा प्राप्त किया गया है। प्रेजेंटेशनल रैपर्स समाहित होते हैं, aria-* गुण निपटाए जाते हैं, और इंटरएक्टिव तत्वों को लेबल किया जाता है।
यह संरचना इस कारण से है कि एजेंट इसे पसंद करते हैं। link: Books to Scrape एक तरीके से सीधे क्रियात्मक है जिसमें <div class="col-sm-8 h1"><a href="..."> नहीं है। वृक्ष पहुँच क्षेत्र के द्वारा खुले तौर पर प्रस्तुत किया जाता है Chrome DevTools प्रोटोकॉल, और यह वही डेटा है जो Chrome अपने स्वयं के पहुँच पेन में प्रस्तुत करता है। अगर CDP स्वयं नया है, तो प्रोटोकॉल प्राइमर इस लेख पर परिवहन को कवर करता है।
इंस्टॉल
bash
pip install playwright tiktoken
playwright install chromium
tiktoken केवल टोकन की संख्या गिनने के लिए है; निष्कर्षण को केवल Playwright की आवश्यकता है। सत्यापन रन ने Playwright 1.59.0 और tiktoken 0.12.0 का उपयोग किया।
वृक्ष को खींचें
Playwright एक कच्चा CDP सत्र प्रस्तुत करता है, यही है जिससे आप उन क्षेत्रों तक पहुँचते हैं जिनका वह लपेटता नहीं है:
python
cdp = page.context.new_cdp_session(page)
nodes = cdp.send("Accessibility.getFullAXTree")["nodes"]
प्रत्येक नोड एक डिक्ट है जिसका role और name स्वयं एक value की कुंजी वाली वस्तुएँ हैं। अधिकांश नोड्स का कोई नाम नहीं होता — कंटेनर, अनदेखे नोड्स, और लेआउट बक्से — इसलिए उपयोगी प्रक्षिप्ति नामित के लिए भूमिका और नाम है:
python
def ax_lines(nodes, roles=None):
lines = []
for node in nodes:
role = (node.get("role") or {}).get("value", "")
name = ((node.get("name") or {}).get("value") or "").strip()
if not name:
continue
if roles is not None and role not in roles:
continue
lines.append(f"{role}: {name}")
return lines
एक लाइव पुस्तक कैटलॉग पर जो पंक्तियाँ उत्पन्न करता है:
text
RootWebArea: All products | Books to Scrape - Sandbox
heading: All products
link: Books to Scrape
StaticText: We love being scraped!
link: Home
StaticText: /
InlineTextBox: /
उन सात पंक्तियों में से दो समान स्लैश हैं। वह प्रतिलिपि पूरी लागत कहानी है।
इसे विकल्पों के खिलाफ मापें
समान पृष्ठ के तीन प्रतिनिधित्वों के लिए टोकन की संख्या गिनें:
python
def measure(page, label):
html = page.content()
text = page.evaluate("document.body.innerText")
cdp = page.context.new_cdp_session(page)
nodes = cdp.send("Accessibility.getFullAXTree")["nodes"]
full = "\n".join(ax_lines(nodes))
acts = "\n".join(ax_lines(nodes, INTERACTIVE))
roles = [(n.get("role") or {}).get("value", "") for n in nodes]
text
raw html tokens= 9824 chars=51004
innerText tokens= 582 chars=2029
AX full tokens= 5951 named_nodes=864
AX interactive only tokens= 742 nodes=114
AX total nodes 1401
StaticText nodes 267
InlineTextBox nodes 391
price in html/text/ax: True/True/True
पूर्ण पहुँच वृक्ष की लागत 5,951 टोकन innerText के 582 के खिलाफ है। यह उसी पृष्ठ के सामान्य पाठ का 10.2× है, और इसके प्रतिस्थापन के लिए अपेक्षित कच्चे HTML का लगभग 60% है।
भूमिका की गणनाएँ इसे समझाती हैं। 1,401 नोड्स में से, 267 StaticText हैं और 391 InlineTextBox हैं — 658 नोड्स, वृक्ष का लगभग आधा, उस पाठ के लिए समर्पित जो पृष्ठ में पहले से एक बार मौजूद है। InlineTextBox नोड्स लेआउट फ्रैगमेंट होते हैं: एक वाक्य जो दो प्रस्तुत पंक्तियों में विभाजित होता है, उनके दो बनाता है। पूर्ण वृक्ष भेजने का मतलब है कि हर स्ट्रिंग के लिए कम से कम दो बार भुगतान करना।
स्पष्ट रूप से कहने के लायक: कुछ भी नहीं खोया गया। कीमत £51.77 HTML में मौजूद है, innerText में, और पहुँच वृक्ष में। इस पृष्ठ पर वृक्ष अधिक महंगा है, कम नहीं।
उस पर फ़िल्टर करें जिस पर एजेंट कार्य कर सकता है
एक पृष्ठ पढ़ने वाला एजेंट को पाठ की आवश्यकता होती है। एक पृष्ठ प्रबंधित करने वाला एजेंट को उन चीजों की आवश्यकता होती है जिन पर वह क्लिक और टाइप कर सकता है। वे भूमिकाओं का एक छोटा सेट हैं:
python
INTERACTIVE = {"link", "button", "textbox", "combobox", "checkbox", "radio", "menuitem", "tab"}
उस सेट को उसी फ़ंक्शन में पास करने से वृक्ष 114 नोड्स और 742 टोकन में संकुचित हो जाता है — 1.3× innerText, और अप्रFiltered प्रारूप की तुलना में 8× सस्ता। हर लिंक और नियंत्रण अपने पहुँच योग्य नाम को बनाए रखता है, यह वह है जिस पर क्लिक निर्देश संदर्भित करता है।
यह एक विकल्प के बजाय विभाजन का सुझाव देता है। जब मॉडल को पढ़ने और निकालने की आवश्यकता हो, तो innerText का उपयोग करें, जब इसे निर्णय लेना हो कि क्या संचालित करना है, तो भूमिका-फिल्टर किए गए वृक्ष का उपयोग करें, और जब कार्य को दोनों की आवश्यकता हो, तो दोनों भेजें — एक साथ वे 1,324 टोकन हैं, अभी भी कच्चे HTML का एक आठवां हिस्सा। एजेंट लूप गाइड बताती है कि उस निर्णय के बाद क्या होता है।
इसे स्क्रैपिंग ब्राउज़र पर चलाएँ
ऊपर कुछ भी स्थानीय ब्राउज़र की आवश्यकता नहीं है। Scrapeless स्क्रैपिंग ब्राउज़र वही प्रोटोकॉल बोलता है, इसलिए CDP सत्र और पहुंच कॉल अपरिवर्तित हैं — केवल कनेक्शन भिन्न है:
python
endpoint = (
"wss://browser.scrapeless.com/api/v2/browser"
f"?token={os.environ['SCRAPELESS_API_KEY']}&sessionTTL=180&proxyCountry=ANY"
)
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(endpoint, timeout=90000)
page = browser.new_page()
page.goto(URL, wait_until="domcontentloaded")
measure(page, "Scrapeless Scraping Browser")
browser.close()
क्लाउड रन ने हर मैट्रिक्स पर समान आंकड़े लौटाए: 9,824 / 582 / 5,951 / 742 टोकन, 1,401 नोड, वही StaticText और InlineTextBox की गिनती। इसका व्यावहारिक परिणाम है। आपके लैपटॉप और उत्पादन के बीच स्विच करने वाला एक पृष्ठ प्रतिनिधित्व एजेंट व्यवहार को दोहराने योग्य नहीं बनाएगा; यह ऐसा नहीं करता है। कुंजी को पर्यावरण में SCRAPELESS_API_KEY के रूप में रखें, और शेष सत्र पैरामीटर के लिए स्क्रैपिंग ब्राउज़र परिचय देखें।
शुरू करने में एक मिनट लगता है — एक निशुल्क Scrapeless खाता बनाएँ और मुफ्त योजना इस रन को कवर करती है।
इसे चलाएँ
bash
export SCRAPELESS_API_KEY="your-api-key"
python3 ax_demo.py
जांच रन से पूरा आउटपुट:
text
playwright 1.59.0 | tiktoken 0.12.0
[local chromium]
raw html tokens= 9824 chars=51004
innerText tokens= 582 chars=2029
AX full tokens= 5951 named_nodes=864
AX interactive only tokens= 742 nodes=114
AX total nodes 1401
StaticText nodes 267
InlineTextBox nodes 391
price in html/text/ax: True/True/True
[Scrapeless Scraping Browser]
raw html tokens= 9824 chars=51004
innerText tokens= 582 chars=2029
AX full tokens= 5951 named_nodes=864
AX interactive only tokens= 742 nodes=114
AX total nodes 1401
StaticText nodes 267
InlineTextBox nodes 391
price in html/text/ax: True/True/True
ratios vs innerText: html=16.9x ax_full=10.2x ax_interactive=1.3x
समस्या निवारण
Accessibility.getFullAXTree बहुत कम नोड लौटाता है। वृक्ष आलस्य से बनाया गया है। सामग्री का अनुरोध करने से पहले नेविगेट करें और सामग्री के लिए प्रतीक्षा करें, और यदि आपका ग्राहक इसे स्वचालित रूप से नहीं करता है, तो पहले Accessibility.enable को कॉल करें।
प्रत्येक नोड का नाम खाली है। आप सीधे node["name"] पढ़ रहे हैं। दोनों role और name वस्तुएँ हैं — स्ट्रिंग node["name"]["value"] पर है।
एक ही पृष्ठ के दो रनों के बीच नोड की गिनती अलग होती है। InlineTextBox नोड लाइन लपेटने का पालन करते हैं, इसलिए एक अलग व्यू पोर्ट चौड़ाई यह बदल देती है कि वे कितने हैं। जब गिनती स्वयं मायने रखती है, तो एक स्पष्ट व्यू पोर्ट सेट करें।
वृक्ष कुछ ऐसा छोड़ देता है जो स्क्रीन पर दृश्य है। सामग्री जिसका मार्क aria-hidden है, और केवल CSS ::before/::after द्वारा उत्पन्न पाठ, जानबूझकर अनुपस्थित है। इसके बजाय DOM से पढ़ें; पहुंच वृक्ष इसका विकल्प नहीं है।
भूमिकाएं अपरिचित लगती हैं। StaticText, InlineTextBox, और RootWebArea आंतरिक Chrome भूमिकाएँ हैं न कि ARIA वाली, यही कारण है कि ARIA-केवल अनुमति सूची पर फ़िल्टर करने से वृक्ष का अधिकांश भाग हटा दिया जाता है। कोर एक्सेसिबिलिटी एपीआई मैपिंग्स परिभाषित करती हैं कि किसी ब्राउज़र को किन भूमिकाओं का प्रदर्शन करना आवश्यक है; उस सेट के अलावा जो कुछ भी इंजन-विशिष्ट है।
निष्कर्ष
पहुंच वृक्ष यह अच्छा उत्तर है कि एक एजेंट को क्या दिया जाना चाहिए, और इसके कच्चे रूप में एक खराब डिफ़ॉल्ट है। यहां मापी गई पृष्ठ पर इसकी लागत 5,951 टोकन है — यह आमतौर पर यह माना जाता है कि यह सामान्य पाठ को संकुचित करता है — क्योंकि इसके लगभग आधे नोड वहां उत्पन्न पाठ का वर्णन करने के लिए हैं जो पृष्ठ पहले ही एक बार कह चुका है।
जिन भूमिकाओं पर एक एजेंट कार्य कर सकता है, उन्हीं पर फ़िल्टर किया गया, वही वृक्ष 742 टोकन है और फिर भी हर नियंत्रण का नाम देता है। यह वह संस्करण है जिसे एक प्रॉम्प्ट में रखना है, जब कार्य को पढ़ने की आवश्यकता भी होती है तो innerText के साथ जोड़ा जाता है। अपने स्वयं के लक्ष्य पर दोनों को मापें: यहाँ की संख्या एक सूची पृष्ठ से आती है, और अनुपात पूरी तरह से इस पर निर्भर करता है कि पृष्ठ पर कितना प्रोज़ है और कितना नियंत्रण है।
क्या आप इसे आजमाने के लिए तैयार हैं? Scrapeless मुफ्त योजना के साथ शुरू करें और उच्च मात्रा के लिए वर्तमान मूल्य निर्धारण देखें।
सामान्य प्रश्न
प्रश्न: क्या मुझे HTML के बजाय पहुँच वृक्ष भेजना चाहिए?
एक फ़िल्टर किया हुआ संस्करण भेजें। अनफिल्टर्ड में 5,951 टोकन थे जबकि कच्चे HTML के लिए 9,824 — एक बचत, लेकिन अपेक्षा से कहीं कम। इंटरएक्टिव भूमिकाओं पर सीमित होने पर यह 742 पर गिर जाता है, जो वास्तविक कमी है।
प्रश्न: क्या पहुँच वृक्ष सामान्य पाठ से सस्ता है?
नहीं, और यह सामान्य भ्रांति है। यहां मापी गई पृष्ठ पर इसकी लागत 10.2× innerText थी। वृक्ष का मूल्य वह भूमिका लेबल है जो यह जोड़ता है, न कि एक छोटा.payload।
प्रश्न: इतनी InlineTextBox नोड्स क्यों हैं?
वे लेआउट फ्रagments हैं — पाठ की प्रत्येक उत्पन्न पंक्ति के लिए एक। एक वाक्य जो दो पंक्तियों में लिपटा होता है, उनके ऊपर एक StaticText नोड पर उसी स्ट्रिंग को होल्ड करते हुए दो उत्पन्न करता है। यही कारण है कि परीक्षण पृष्ठ पर 1,401 नोड्स में से 658 पाठ की डुप्लीकेट थे।
प्रश्न: क्या पेड़ में पृष्ठ पर सब कुछ शामिल है?
बिलकुल नहीं। aria-hidden सामग्री और CSS प्सेडो-तत्वों द्वारा उत्पन्न पाठ जानबूझकर बाहर रखा गया है। यहां मापी गई पृष्ठ पर कुछ भी आवश्यक गायब नहीं था — कीमत तीनों प्रतिनिधित्वों में दिखाई दी — लेकिन अपने लक्ष्य पर इसकी पुष्टि करें, मानने के बजाय।
प्रश्न: क्या मुझे पहुंचने के पेड़ को पढ़ने के लिए एक स्थानीय क्रोम की आवश्यकता है?
नहीं। इस गाइड में क्लाउड रन ने स्थानीय क्रोमियम के लिए बाइट-एकसमान संख्याएँ उत्पन्न कीं, क्योंकि दोनों समान प्रोटोकॉल बोलते हैं। केवल कनेक्शन लाइन बदली है।
स्क्रैपलेस में, हम केवल सार्वजनिक रूप से उपलब्ध डेटा का उपयोग करते हैं, जबकि लागू कानूनों, विनियमों और वेबसाइट गोपनीयता नीतियों का सख्ती से अनुपालन करते हैं। इस ब्लॉग में सामग्री केवल प्रदर्शन उद्देश्यों के लिए है और इसमें कोई अवैध या उल्लंघन करने वाली गतिविधियों को शामिल नहीं किया गया है। हम इस ब्लॉग या तृतीय-पक्ष लिंक से जानकारी के उपयोग के लिए सभी देयता को कोई गारंटी नहीं देते हैं और सभी देयता का खुलासा करते हैं। किसी भी स्क्रैपिंग गतिविधियों में संलग्न होने से पहले, अपने कानूनी सलाहकार से परामर्श करें और लक्ष्य वेबसाइट की सेवा की शर्तों की समीक्षा करें या आवश्यक अनुमतियाँ प्राप्त करें।



