गूगल सर्च स्क्रैपर एपीआई: पांच डिफ़ॉल्ट जो खाली डेटा लौटाते हैं
Lead Scraping Automation Engineer
TL;DR:
- Google सर्च अभिनेता से एक
200डेटा का प्रमाण नहीं है: प्रतिक्रिया एक खालीorganic_resultsऐरे, एक लिस्टिंग के बजाय एक विज्ञापन प्लेसहोल्डर, या ऐसे क्षेत्र को ले जा सकती है जो डिज़ाइन द्वारा खाली है। - Dify दो API-key डिफ़ॉल्ट्स को पूर्व-भरता है जो दोनों
401को{"code":14404,"message":"invalid access token"}के साथ उत्पन्न करते हैं — हेडर नामAuthorizationपर डिफ़ॉल्ट होता है और हेडर प्रीफिक्सBasicपर डिफ़ॉल्ट होता है, और अभिनेता दोनों को स्वीकार नहीं करता। - एक n8n वर्कफ़्लो बिना किसी त्रुटियों के मान्य हो सकता है और फिर भी रनटाइम पर विफल हो सकता है, क्योंकि संस्करण 2.34.4 में कोड नोड सैंडबॉक्स वैश्विक
URLकंस्ट्रक्टर को उजागर नहीं करता। - एक एजेंट जिसे एक सर्च टूल दिया गया है वह बिना इसे कॉल किए उत्तर दे सकता है, ऐसे धाराप्रवाह टेक्स्ट का उत्पादन करता है जो कभी भी API को नहीं छूता; टूल कॉल को गिनने से वह चुप्पी की चूक एक विफलता में बदल जाती है।
- लोकल-पैक रिकॉर्ड
place_id,gps_coordinates, औरthumbnailको खाली लौटाते हैं, औरphone,type, औरhoursको एक अग्रणी स्थान के साथ — दोनों प्रलेखित व्यवहार हैं, डिबग करने के लिए दोष नहीं हैं।
Google सर्च अभिनेता क्या लौटाता है
scraper.google.search अभिनेता एक क्वेरी लेता है और JSON के रूप में एक पार्स किया हुआ SERP लौटाता है। यह डीप सर्पएपीआई का Google सतह है, और यह आमतौर पर एक वर्कफ़्लो बिल्डर या एजेंट ढांचे में वायर किए गए पहले अभिनेता होते हैं, क्योंकि एक रैंक सूची रैंक ट्रैकिंग और लीड अनुसंधान दोनों को समान रूप से अच्छी तरह से फ़ीड करती है।
नीचे की विफलताएँ असाधारण नहीं हैं। ये एक अनुरोध के बीच के अंतर से आती हैं जो स्वीकृत है और एक पेलोड जो उपयोगी है — और इनमें से प्रत्येक को इस लेख में उदाहरण के रूप में उपयोग किए जाने वाले चार होस्ट प्लेटफार्मों से पुन: उत्पन्न किया जा सकता है: Dify, n8n, Activepieces, और LangChain।
अनुरोध: अंत बिंदु, अभिनेता, और पैरामीटर
हर कॉल एक POST एकल अंत बिंदु पर दो क्षेत्रों के साथ होती है। actor स्क्रैपर का चयन करता है और input इसके पैरामीटर ले जाता है:
bash
curl -sS -X POST https://api.scrapeless.com/api/v1/scraper/request \
-H 'Content-Type: application/json' \
-H "x-api-token: $SCRAPELESS_API_KEY" \
-d '{"actor":"scraper.google.search","input":{"q":"web scraping api"}}'
तीन पैरामीटर अधिकांश काम को कवर करते हैं:
| पैरामीटर | उद्देश्य |
|---|---|
q |
क्वेरी स्ट्रिंग। |
tbm |
परिणाम प्रकार। lcl स्थानीय पैक को वेब परिणामों के बजाय लौटाता है। |
start |
पृष्ठनुमा के लिए परिणाम ऑफसेट - स्थानीय पैक पर प्रति पृष्ठ 20। |
प्रमाणीकरण हेडर x-api-token है। वह नाम वह क्षेत्र है जिसे एक नो-कोड प्लेटफॉर्म सबसे अधिक संभावना अपने डिफ़ॉल्ट के साथ भरेगा। HTTP अर्थव्यवस्था विनिर्देश 401 प्रतिक्रियाओं के लिए उस चुनौती की अपेक्षा करता है जो संसाधन की अपनी प्रमाणीकरण योजना से जुड़ी होती है, इसलिए एक प्लेटफॉर्म जो Authorization मानता है वह उचित हो रहा है — यह बस इस अंत बिंदु के लिए गलत योजना मान रहा है।
प्रतिक्रिया लिफाफा
आपको डेटा पढ़ने से पहले लिफाफा पढ़ना चाहिए। एक सफल Google सर्च कॉल इन शीर्ष-स्तरीय कुंजियों को लौटाता है:
json
// illustrative sample — key shape only; values omitted
{
"search_information": {},
"organic_results": [],
"related_searches": [],
"pagination": {},
"metadata": {}
}
उस आकार से दो बातें निकलती हैं। वहां कोई success ध्वज नहीं है जिस पर शाखा के लिए जाएं, इसलिए organic_results की उपस्थिति और लंबाई संकेत है। और इस लिफाफे में कोई पीपल-ऑल्सो-आस्क ब्लॉक नहीं है — एक क्वेरी जो ब्राउज़र में संबंधित प्रश्न दिखाती है वह यहां related_searches लौटाती है, इसलिए एक वर्कफ़्लो जो प्रश्नों के ऐरे की अपेक्षा करता है None प्राप्त करता है और एक खाली कॉलम लिखता है।
tbm को lcl पर सेट करने के साथ, परिणाम local_results.places[] पर जाते हैं बजाय organic_results[] के। एक पाइपलाइन जो एक पथ को कठोर करती है वह जब दूसरे का अनुरोध किया जाता है तब चुपचाप कुछ नहीं उत्पन्न करती है।
कोड में प्रतिक्रिया पढ़ना
अनुरोध के बाद का कथन वह भाग है जो कॉपी करने के लायक है। यह उदाहरण खाली सूची लौटाने के बजाय उठाता है, इसलिए एक विफलता वहां सतह पर होती है जहां यह हुई थी, बजाय इसके कि तीन कदम बाद एक स्प्रेडशीट में:
python
import json
import os
import urllib.request
ENDPOINT = "https://api.scrapeless.com/api/v1/scraper/request"
def search(query: str) -> dict:
payload = json.dumps({"actor": "scraper.google.search", "input": {"q": query}}).encode()
request = urllib.request.Request(
ENDPOINT,
data=payload,
headers={
"Content-Type": "application/json",
"x-api-token": os.environ["SCRAPELESS_API_KEY"],
},
)
# urlopen raises HTTPError on any 4xx or 5xx, so a rejected call never reaches the parser.
with urllib.request.urlopen(request, timeout=120) as response:
return json.loads(response.read())
serp = search("web scraping api")
organic = serp.get("organic_results") or []
if not organic:
raise SystemExit(f"no organic_results in the response; envelope was {sorted(serp)}")
print(f"organic_results: {len(organic)}")
print(f"first result: {organic[0]['title']}")
print(f"envelope keys: {sorted(serp)}")
गैर-मौजूद और खाली अलग-अलग स्थितियाँ हैं, और JSON इंटरचेंज प्रारूप विनिर्देश "कुंजी छोड़ दी गई थी" और "मान एक खाली स्ट्रिंग है" को अलग करने में कोई मदद नहीं करता। तय करें कि आपकी पाइपलाइन इनमें से किसे त्रुटि के रूप में मानती है इससे पहले कि आप पहला डालें।
फ्री प्लान पर इसके माध्यम से काम करना यहां वर्णित हर व्यवहार को देखने के लिए पर्याप्त है — एक Scrapeless खाता बनाएँ और नीचे चारों प्लेटफार्मों पर समान की का उपयोग करें।
पांच डिफ़ॉल्ट जो खाली डेटा लौटाते हैं
API-key हेडर जिसे आपका प्लेटफ़ॉर्म पूर्व-भरता है वह गलत है
Dify 1.16.1 में, एक कस्टम टूल के रूप में OpenAPI स्कीमा को आयात करना और API Key प्रमाणीकरण का चयन करना दो क्षेत्रों को उस डिफ़ॉल्ट पर छोड़ देता है जिन्हें अभिनेता अस्वीकार करता है। हेडर नाम Authorization पर डिफ़ॉल्ट होता है, और हेडर प्रीफिक्स Basic पर डिफ़ॉल्ट होता है — जो x-api-token: Basic <key> भेजता है जबकि आप नाम को सही करते हैं। दोनों समान प्रतिक्रिया उत्पन्न करते हैं:
json
{ "code": 14404, "message": "invalid access token" }
एक त्रुटि संदेश, दो स्वतंत्र कारण, जो इसे निदान करने में महंगा बनाते हैं। कार्यशील कॉन्फ़िगरेशन सभी तीन नाम रखता है:
| क्षेत्र | मान |
|---|---|
| प्रमाणीकरण प्रकार | API Key |
| हैडर नाम | x-api-token |
| हैडर प्रीफ़िक्स | Custom |
Dify भी एक नेस्टेड अनुरोध-शरीर वस्तु को स्ट्रिंग पैरामीटर में समतल करता है, इसलिए input क्षेत्र पाठ के रूप में आता है न कि संरचित वस्तु के रूप में। एक वस्तु और एक JSON स्ट्रिंग दोनों स्वीकार किए जाते हैं, यही कारण है कि इसे लगभग कभी विशेष ध्यान नहीं मिलता जब तक एक डाउनस्ट्रीम नोड input.q को पढ़ने की कोशिश नहीं करता।
एक कार्यप्रवाह जो मान्य है, फिर भी रनटाइम पर विफल हो सकता है
स्थैतिक मान्यता और निष्पादन n8n कोड नोड में असहमत होते हैं। एक कार्यप्रवाह जो new URL(link).hostname का उपयोग करता है, परिणामों को डोमेन द्वारा समूहित करता है, शून्य त्रुटियों के साथ मान्य होता है, फिर पहले आइटम पर URL is not defined के साथ विफल हो जाता है। संस्करण 2.34.4 में सैंडबॉक्स उस वैश्विक को प्रदर्शित नहीं करता है, भले ही WHATWG URL मानक इसे एक वेब एपीआई कंस्ट्रक्टर के रूप में परिभाषित करता है और n8n की अपनी कोड नोड के बिना URL कंस्ट्रक्टर के विफल होने की रिपोर्ट इस लक्षण को रिकॉर्ड करती है।
संकेतक नाम को स्ट्रिंग संचालन के साथ निकालें:
javascript
// The Code node sandbox does not expose the global URL constructor,
// so the hostname comes from string operations.
const hostname = (link) =>
link ? link.replace(/^[a-z]+:\/\//i, '').replace(/^www\./i, '').split(/[/?#]/)[0] : '';
const results = [
{ position: 1, link: 'https://www.scrapeless.com/hi/product/deep-serp-api' },
{ position: 2, link: 'https://docs.scrapeless.com/en/deep-serp-api/quickstart/introduction/' },
];
for (const result of results) {
console.log(result.position, hostname(result.link));
}
एक कार्यप्रवाह निर्माता में मान्यता ग्राफ की जाँच करती है, न कि किसी नोड के भीतर के कोड की। इसलिए एक हरा चेक नहीं बताता है कि क्या एक कोड नोड कार्यान्वित होगा।
वह कदम संदर्भ जो कुछ भी नहीं हल करता है
Activepieces 0.82.0 में, एक HTTP कदम का विश्लेषित JSON body के तहत रहता है। संदर्भ {{step_1.body.organic_results}} है, और {{step_1.organic_results}} पूरी तरह से कुछ भी नहीं हल करता है — कोई त्रुटि, कोई चेतावनी, बस एक खाली लूप और एक चलन जो सफलता की रिपोर्ट करता है। जब tbm को lcl पर सेट किया जाता है, तो पथ {{step_1.body.local_results.places}} होता है।
एक अनुपस्थित-संदर्भ विफलता एक वास्तविक खाली परिणाम सेट के समान दिखती है, इसलिए किसी डेटा समस्या की तलाश में जाने से पहले संदर्भ पथ की जाँच करें।
वह एजेंट जो बिना उपकरण को कॉल किए जवाब देता है
एक एजेंट को एक खोज उपकरण दें और यह इसका उपयोग नहीं कर सकता है। एक छोटा मॉडल जिसे दोनों खोज उपकरण और फ़ेच उपकरण दिया गया है, अक्सर खोज करेगा, फिर "पृष्ठ कहता है" का वर्णन करते समय परिणाम के स्निपेट्स से उत्तर देगा — पृष्ठ को कभी नहीं फ़ेच करते हुए। गद्य फ़्लूएंट है और उद्धरण निहित है, इसलिए आउटपुट में कुछ भी उत्तर को असंबद्ध नहीं बताता है।
समाधान एक असर्शन है, बेहतर संकेत नहीं। उपकरण कॉल की गणना करें और शून्य को एक विफलता मानें:
नोट: यह स्निपेट एक मौजूदा एजेंट को लपेटता है, इसलिए इसे चलाने के लिए एक निर्मित LangChain एजेंट और एक मॉडल-प्रदाता कुंजी की आवश्यकता होती है। यह जिस पर निर्भर करता है, वह मानक
agent.stream(...)आउटपुट है।
python
tool_calls = 0
for chunk in agent.stream({"messages": [("human", question)]}, stream_mode="values"):
message = chunk["messages"][-1]
tool_calls += len(getattr(message, "tool_calls", None) or [])
if tool_calls == 0:
raise SystemExit("the model answered without calling a tool; the answer is not grounded")
एकल-उपकरण निर्देश छोटे मॉडलों पर विश्वसनीय होते हैं। चेन किए गए निर्देश — खोज, फिर शीर्ष परिणाम लाना — वह जगह है जहाँ उपकरण कॉल चुपचाप गायब हो जाता है, इसलिए कोड में कदम विभाजित करें और मॉडल को एक समय में एक कॉल संभालने दें।
जानबूझकर खाली क्षेत्र
कुछ खाली मान सही होते हैं। स्थानीय-पैक परिणामों में, place_id, gps_coordinates, और thumbnail खाली लौटते हैं, और phone, type, और hours अग्रणी स्थान के साथ आते हैं। न तो एक दोष है, और दोनों भोले कोड को तोड़ते हैं: एक ट्रेलिंग-स्पेस असमानता एक डीडुप्लीकेशन कुंजी को डुप्लिकेट में बदल देती है, और एक खाली place_id को त्रुटि के रूप में मानने से आपको वह व्यवहार डिबगिंग करता है जो दस्तावेज़ित जैसा काम कर रहा है।
आने के रास्ते में सामान्यीकृत करें:
| क्षेत्र | व्यवहार | हैंडलिंग |
|---|---|---|
phone, type, hours |
अग्रणी स्थान | संग्रहण या तुलना से पहले ट्रिम करें। |
place_id, gps_coordinates, thumbnail |
स्थानीय परिणामों पर खाली | इसे शून्य योग्य मानें; उनके आधार पर रिकॉर्ड को गेट न करें। |
organic_results बनाम local_results.places |
tbm पर निर्भर करता है |
अनुरोध से पथ का चयन करें, अनुमान नहीं लगाकर। |
उसी अनुशासन की गणना पर भी जानकारी होती है। एक परिणाम श्रृंखला में प्रायोजित स्लॉट और लेआउट प्लेसहोल्डर्स शामिल हो सकते हैं जिनके साथ लिस्टिंग होती हैं, इसलिए श्रृंखला की लंबाई परिणामों की संख्या नहीं होती है — या हर संख्या डाउनस्ट्रीम उस विज्ञापन लोड को विरासत में लेती है जो पृष्ठ ने परोसने के लिए प्रस्तुत किया था।
निष्कर्ष
एक नो-कोड स्क्रैपिंग सेटअप में महंगे विफलताएँ कुछ भी न रखकर हरे रंग में समाप्त होती हैं: एक प्रमाणीकरण हैडर जो आपके प्लेटफ़ॉर्म द्वारा पूर्व-भरे हुए हैं, एक वेब एपीआई वैश्विक जो सैंडबॉक्स छोड़ता है, एक संदर्भ पथ जो एक खंड को खो देता है, एक एजेंट जो उपकरण को छोड़ देता है, या एक क्षेत्र जो हमेशा खाली रहने वाला था। प्रत्येक में एक-लाइन का समाधान होता है और इसे इंगित करने वाला कोई त्रुटि संदेश नहीं होता है।
दो आदतें सभी पाँचों को पकड़ती हैं। डेटा से पहले प्रतिक्रिया लिफाफा पढ़ें, और जो आप अपेक्षा करते हैं उस पर दावा करें - एक गैर-खाली एरे, एक टूल कॉल, एक रिकॉर्ड प्रकार - ताकि एक मौन चूक उस कदम पर एक ज़ोरदार विफलता बन जाए जिसने इसे कारण बनाया। n8n स्क्रैपिंग कार्यप्रवाह गाइड और LangChain एकीकरण वॉकथ्रू दिखाते हैं कि एक ही अभिनेता अंत से अंत तक कैसे जुड़ा होता है जब वे चेक पूरा हो जाते हैं।
क्या आप एक SERP सतह के खिलाफ निर्माण करने के लिए तैयार हैं जो एक दस्तावेज़ लिफाफा लौटाता है? पूर्ण पैरामीटर सेट के लिए डीप SerpApi दस्तावेज़ की जांच करें, योजनाएँ और शामिल मात्रा की समीक्षा करें, और मुफ्त योजना पर शुरू करें।
FAQ
Q: क्यों मेरा Google खोज अभिनेता कॉल 200 के साथ एक खाली organic_results एरे लौटाता है?
एक खाली organic_results एरे के साथ एक 200 का अर्थ है कि अनुरोध को स्वीकार किया गया और पार्स किया गया लेकिन उस क्वेरी रूप के लिए कोई वेब परिणाम उत्पन्न नहीं हुए। क्रम में तीन चीजें जांचें: क्या tbm को lcl पर सेट किया गया था, जो परिणामों को local_results.places[] पर ले जाता है; क्या क्वेरी खुद में परिणाम इरादा है; और क्या आपका प्लेटफ़ॉर्म पार्स किए गए शरीर को लिफाफा के बजाय पढ़ रहा है। प्रतिक्रिया में कोई success ध्वज नहीं है, इसलिए एरे की लंबाई केवल संकेत है।
Q: जब कुंजी सही होती है, तो {"code":14404,"message":"invalid access token"} क्या कारण है?
उस प्रतिक्रिया का अर्थ है कि कुंजी उस रूप में नहीं आई जिसे अंत बिंदु अपेक्षा करता है। हेडर को x-api-token होना चाहिए जो केवल कुंजी को ले जाता है। प्लेटफ़ॉर्म जो Authorization पर डिफ़ॉल्ट करते हैं, या जो Basic या Bearer को मान में जोड़ते हैं, एक हेडर भेजते हैं जिसे अंत बिंदु पढ़ नहीं सकता - और संदेश हर मामले में समान होता है, इसलिए हेडर नाम और किसी भी प्रीफिक्स सेटिंग को अलग से सत्यापित करें।
Q: क्यों मेरा n8n कोड नोड URL is not defined के साथ विफल होता है जब कार्यप्रवाह मान्य होता है?
n8n 2.34.4 में कोड नोड सैंडबॉक्स वैश्विक URL कन्स्ट्रक्टर को उजागर नहीं करता है, और कार्यप्रवाह मान्यता नोड कोड निष्पादित नहीं करती है, इसलिए ग्राफ अपने चेक पास करता है और पहली वस्तु पर रन विफल हो जाता है। स्ट्रिंग ऑपरेशनों के साथ होस्टनेम को पार्स करें, या यूआरएल हेंडलिंग को एक नोड में स्थानांतरित करें जो एपीआई प्रदान करता है।
Q: मैं कैसे जानूं कि एक एजेंट ने वास्तव में खोज उपकरण का उपयोग किया है?
स्ट्रीम किए गए संदेशों पर टूल कॉल की गणना करें और जब संख्या शून्य हो तो विफल रहें। एक मॉडल बिना किसी टूल को आमंत्रित किए एक संपूर्ण, आत्मविश्वासी उत्तर उत्पन्न कर सकता है, और पाठ में कुछ भी उस उत्तर को ग्राउंडेड उत्तर से अलग नहीं करता है। टूल-कॉल की गिनती को एक कठिन आवश्यकता के रूप में मानें बजाय इसके कि प्रोज़ को निरीक्षण किया जाए।
Q: क्या खाली place_id और gps_coordinates मान एक बग हैं?
नहीं। स्थानीय-पैक रिकॉर्ड place_id, gps_coordinates, और thumbnail को खाली लौटाते हैं, इसलिए वे फ़ील्ड डिजाइन के अनुसार नल योग्य हैं। रिकॉर्ड को रखें और उन फ़ील्ड से स्थान को भरें जो मौजूद हैं बजाय इसके कि पंक्तियों को त्यागें या अपेक्षित व्यवहार के चारों ओर त्रुटि हैंडलिंग जोड़ें।
Q: क्यों मेरा Activepieces लूप शून्य बार दोहराता है जब HTTP कदम सफल होता है?
पार्स की गई प्रतिक्रिया body के तहत निहित है, इसलिए {{step_1.organic_results}} कुछ नहीं को हल करता है जबकि {{step_1.body.organic_results}} एरे को हल करता है। एक गायब संदर्भ Activepieces 0.82.0 में कोई त्रुटि उत्पन्न नहीं करता है - लूप बस कुछ भी प्राप्त नहीं करता है और रन अभी भी सफलता की रिपोर्ट करता है, जिससे यह शून्य परिणाम सेट से अलग नहीं होता जब तक आप पथ की जांच न करें।
स्क्रैपलेस में, हम केवल सार्वजनिक रूप से उपलब्ध डेटा का उपयोग करते हैं, जबकि लागू कानूनों, विनियमों और वेबसाइट गोपनीयता नीतियों का सख्ती से अनुपालन करते हैं। इस ब्लॉग में सामग्री केवल प्रदर्शन उद्देश्यों के लिए है और इसमें कोई अवैध या उल्लंघन करने वाली गतिविधियों को शामिल नहीं किया गया है। हम इस ब्लॉग या तृतीय-पक्ष लिंक से जानकारी के उपयोग के लिए सभी देयता को कोई गारंटी नहीं देते हैं और सभी देयता का खुलासा करते हैं। किसी भी स्क्रैपिंग गतिविधियों में संलग्न होने से पहले, अपने कानूनी सलाहकार से परामर्श करें और लक्ष्य वेबसाइट की सेवा की शर्तों की समीक्षा करें या आवश्यक अनुमतियाँ प्राप्त करें।



