डेटा-संचालित भर्ती: वेब स्क्रैपिंग के माध्यम से एक स्केलेबल प्रतिभा बुद्धिमत्ता मंच का निर्माण
Expert Network Defense Engineer
मुख्य निष्कर्ष:
- प्रतिभा बाजार बुद्धिमत्ता एक फर्मोग्राफिक समस्या है, न कि एक लोगों की समस्या। वह सिग्नल जो भर्ती रणनीति, प्रतिस्पर्धी बेंचमार्किंग और क्षेत्र योजना को चलाता है, सामूहिक पैटर्न में रहता है — एक कंपनी कितने पद खोलती है, किन कार्यों में, किन शहरों में, और कितनी तेजी से — कभी भी नामित व्यक्तियों में नहीं। विश्लेषण की इकाई को कंपनी-और-भूमिका के स्तर पर बनाए रखें और पूरा पाइपलाइन कानून के सही पक्ष पर रहता है।
- सार्वजनिक भर्ती सिग्नल चार सतहों पर बिखरे हुए हैं। कंपनी की करियर साइटों और एग्रीगेटर्स पर नौकरी पोस्टिंग, कॉर्पोरेट साइटों पर भर्ती खंड, पेशेवर निर्देशिकाओं में फर्मोग्राफिक प्रविष्टियाँ, और नियोक्ता समीक्षा साइटें प्रत्येक एक हिस्से को पकड़ती हैं। एक रेंडर पैटर्न चारों को एकत्र करता है; एक मानक स्कीमा उन्हें जोड़ता है।
- भर्ती गति और बैकफिल व्युत्पन्न मैट्रिक्स हैं, न कि स्क्रैप की गई फ़ील्ड। आप "अत्रिशन" को स्क्रैप नहीं करते। आप समय के साथ पोस्टिंग तारीखों और भूमिका की पहचान को स्क्रैप करते हैं, फिर वेग (प्रति सप्ताह नई मांग) और बैकफिल दबाव (समान भूमिका शीर्षक उसी कंपनी में फिर से प्रकट होना) को गोदाम में निकाला जाता है। DOM आपको अवलोकन देता है; गणित आपको सिग्नल देता है।
- रेंडर कॉल भू-निर्धारित और सत्र-गर्म किया गया है। प्रत्येक सार्वजनिक खोज पृष्ठ एक क्लाउड ब्राउजर के अंदर रेंडर होता है जिसमें अमेरिका का आवासीय निकास, वास्तविक जावास्क्रिप्ट निष्पादन, और एक गर्म सत्र होता है — पहले साइट का मेन पृष्ठ लोड करें, फिर लक्षित खोज URL। पाइपलाइन एक URL के साथ एक देश भेजता है और एक पूर्ण पेंटेड DOM प्राप्त करता है।
- व्यक्तिगत डेटा डिज़ाइन द्वारा बाहर रहता है। यह पाइपलाइन नौकरी के शीर्षक, विभाग, स्थान, वरिष्ठता बैंड और पोस्टिंग की गणना एकत्र करती है — नाम, संपर्क विवरण, या व्यक्तिगत रोजगार इतिहास नहीं। नीचे अनुपालन खंड वह अनुबंध है जो अस्वीकरण को सत्य बनाता है।
- शुरुआत के लिए स्वतंत्र। नए स्क्रैपलेस खातों में मुफ्त स्क्रैपिंग ब्राउज़र रनटाइम शामिल है — app.scrapeless.com पर साइन अप करें।
परिचय: बिखरी हुई पोस्टिंग से भर्ती-मार्केट सिग्नल
प्रतिभा और प्रतिस्पर्धी-ज्ञाता टीमें एक द्वंद्व बिंदु का सामना करती हैं। वे आपको बता सकते हैं कि एक प्रतियोगी आज किसे काम पर रखता है, मोटे तौर पर, लेकिन यह नहीं कि वह प्रतियोगी बना रहा है — और उत्तर सार्वजनिक करियर पृष्ठों पर स्पष्ट दृष्टि में है। एक कंपनी जो एक ही तिमाही में पंद्रह प्लेटफ़ॉर्म-इंजीनियरिंग की मांग खोलती है, वह बाजार को बता रही है कि वह कहाँ निवेश कर रही है। एक कंपनी जो दो महीने में समान स्टाफ-इंजीनियर भूमिका को तीन बार फिर से पोस्ट करती है, वह बाजार को बता रही है कि उसे बैकफिल की समस्या है। ये प्रतिस्पर्धात्मक सिग्नल हैं, और ये किसी भी विश्लेषक रिपोर्ट से तेज़ी से ताज़ा होते हैं।
संरचनात्मक चुनौती "एक नौकरी बोर्ड को स्क्रैप करना" नहीं है। यह कंपनियों की एक बasket के बीच, भर्ती सतहों की एक बास्केट के बीच, क्षेत्रों की एक बास्केट के बीच एक सख्त फैन-आउट संचालित करना है — एक कार्यक्रम पर, हर रन में समान सटीकता garanties के साथ। सार्वजनिक करियर पृष्ठ React और Next.js एप्लिकेशनों में हैं जहां लिस्टिंग हाइड्रेशन के बाद पेंट होती है। एग्रीगेटर्स क्षेत्र और आईपी प्रतिष्ठा के आधार पर परिणाम स्थानीयकृत करते हैं। प्रत्येक अनुरोध को एक एंटी-बॉट स्तर को साफ़ करना होता है और एक पूरी तरह से रेंडर की गई पृष्ठ के रूप में वापस आना होता है, न कि एक खाली खोल। और उन पृष्ठों में से प्रत्येक एक लापरवाह चयनकर्ता से नाम, ईमेल, या एक व्यक्तिगत प्रोफ़ाइल के पास बैठता है — डेटा जिसे यह पाइपलाइन कभी नहीं छूना चाहिए।
यह गाइड प्रतिभा बाजार बुद्धिमत्ता पाइपलाइन की संग्रह परत के वास्तुकला और पायथन कोड के माध्यम से चलती है, जो स्क्रैपलेस स्क्रैपिंग ब्राउज़र पर आधारित है। रेंडर सिद्ध क्लाउड-ब्राउज़र कनेक्शन का उपयोग करता है: यूएस ईग्रेस को पिन करें, मुख्य पृष्ठ पर सत्र को गर्म करें, फिर सार्वजनिक नौकरी-खोज पृष्ठ लोड करें और पोस्टिंग को निकाले। आउटपुट कंपनी-और-भूमिका के अवलोकनों का एक मानकीकृत प्रवाह है जो एक गोदाम को खिलाता है; इनपुट वह कंपनी-और-स्रोत बास्केट है जिसे विश्लेषक परिभाषित करता है। पैटर्न के लिए एक बार पढ़ें; प्रत्येक कंपनी के लिए पुन: उपयोग करें केवल स्रोत-विशिष्ट एक्सट्रैक्टर को बदलकर।
इसके साथ आप क्या कर सकते हैं
- भर्ती-गति बेंचमार्किंग। ट्रैक करें कि एक सेट प्रतियोगियों में से किसने प्रति सप्ताह, प्रत्येक कार्य, प्रत्येक क्षेत्र में कितने पद खोले — और यह रैंक करें कि कौन तेज हो रहा है और कौन भर्तियों को रोक रहा है।
- कार्य-मिक्स विश्लेषण। एक कंपनी जो अपनी पोस्टिंग मिक्स को बिक्री से ML इंजीनियरिंग में बदल रही है, वह एक रणनीति परिवर्तन को स्मार्ट तरीके से बता रही है। पोस्टिंग बास्केट प्रेस विज्ञप्ति से पहले बदलाव को सतह पर लाती है।
- भौगोलिक विस्तार के सिग्नल। एक नए मेट्रो या देश में पोस्टिंग का पहला प्रकट होना यह एक अग्रणी संकेत है कि एक प्रतियोगी एक बाजार को खोल रहा है। क्षेत्र की पिन सिग्नल को चलनों के बीच तुलनीय बनाती है।
- बैकफिल और फिर से पोस्ट पहचान। समय-समय पर उसी कंपनी में फिर से प्रकट होने वाला समान भूमिका शीर्षक बैकफिल-प्रेशर सिग्नल है — पोस्टिंग पहचान और तारीखों से व्युत्पन्न, कभी भी किसी व्यक्ति को ट्रैक करने से नहीं।
- वेतन-बैंड बुद्धिमत्ता। जहाँ पदों पर मुआवजे की सीमा प्रकाशित होती है (कई अमेरिकी राज्यों में अनिवार्य), वह एक भूमिका-स्तरीय वेतन मानक के लिए सार्वजनिक रेखा बनाता है और क्षेत्र।
- नियोक्ता-भावना संदर्भ। सार्वजनिक नियोक्ता समीक्षा साइटों से एकत्रित, गुमनाम रेटिंग वितरण प्रतियोगी के भर्ती ब्रांड की प्रवृत्ति के बारे में डिमांड-साइड पढ़ने को जोड़ता है।
स्क्रेपलेस स्क्रेपिंग ब्राउज़र क्यों टैलेंट इंटेलिजेंस के लिए
स्क्रेपलेस स्क्रेपिंग ब्राउज़र एक अनुकूलन योग्य, एंटी-डिटेक्शन क्लाउड ब्राउज़र है जिसे वेब क्रॉलर्स और एआई एजेंटों के लिए डिजाइन किया गया है। विशेष रूप से एक टैलेंट मार्केट इंटेलिजेंस पाइपलाइन के लिए, यह लाता है:
- 195+ देशों में आवासीय प्रॉक्सियाँ, प्रति सत्र देश के कोड के साथ तालिका — निकासी भूगोल आपके द्वारा मापे गए क्षेत्र के लिए एक फ़ील्ड है।
- क्लाउड-साइड जावास्क्रिप्ट रेंडरिंग। आधुनिक करियर पृष्ठ और एग्रीगेटर एकल-पृष्ठ एप्स हैं; लिस्टिंग ग्रिड हाइड्रेशन के बाद लैंड करता है। क्लाउड ब्राउज़र पोस्ट-पेंट DOM लौटाता है, ताकि आपके चयन असली कार्ड के खिलाफ संबोधित हों, न कि एक खाली खोल के खिलाफ।
- प्रवाह में सत्र गर्म करने की सुविधा। पहले उसी सत्र के भीतर साइट के होमपेज को लोड करना कुकीज़ और क्लाइंट स्थिति स्थापित करता है जिसकी उम्मीद एक सार्वजनिक सर्च पृष्ठ करता है, इसलिए अगली लक्ष्य लोड एक स्वच्छ रेंडर लौटाता है।
- एंटी-डिटेक्शन फिंगरप्रिंटिंग सर्वर-साइड संभाली जाती है। उपयोगकर्ता एजेंट, समय क्षेत्र, WebGL, और कैनवास संकेत क्लाउड में प्रति सत्र यादृच्छिक होते हैं — आपके मशीन पर कोई स्थानीय स्टील्थ-प्लगइन रखरखाव नहीं और न ही ब्राउज़र बाइनरी।
- पूरे पाइपलाइन के लिए एक एपीआई की। रेंडरिंग और आवासीय निकासी एक ही स्क्रेपलेस खाते के खिलाफ बिल करती है; कनेक्ट करने के लिए कोई अलग प्रॉक्सी प्रदाता नहीं है।
अपने एपीआई की के लिए मुफ्त योजना पर जाएँ app.scrapeless.com.
आवश्यकताएँ
- पायथन 3.10 या नया
- एक स्क्रेपलेस खाता और एपीआई की — app.scrapeless.com पर साइन अप करें
pip install playwright lxml pyyaml cssselectऔर एक बारplaywright install chromium(स्थानीय क्रोमियम केवल प्रोटोकॉल को बोलता है; रेंडरिंग क्लाउड में चलती है)- CSS चयनकर्ताओं और एक बुनियादी गोदाम लक्ष्य (स्नोफ्लेक, बिगक्वेरी, डकडीबी, या पोस्टग्रेएस) से परिचितता
- एक कंपनी-और-स्रोत बास्केट फ़ाइल
पाइपलाइन आर्किटेक्चर एक नज़र में
basket.yaml (विश्लेषक-परिभाषित: कंपनियाँ × स्रोत × क्षेत्र)
│
▼
┌──────────────────┐
│ आयोजक │ (कंपनी, स्रोत, क्षेत्र) प्रति एक कार्य; सीमित फैन-आउट
└──────┬───────────┘
│
▼
┌──────────────────┐
│ स्क्रेपलेस │ connect_over_cdp → गर्म होमपेज → लोड सर्च URL
│ (क्लाउड ब्राउज़र) │ अमेरिकी आवासीय निकासी, JS रेंडरिंग, एंटी-डिटेक्शन
└──────┬───────────┘
│ रेंडर की गई HTML
▼
┌──────────────────┐
│ सामान्यीकर्ता │ स्रोत-प्रति एक्स्ट्रक्टर → मानक पदनSchema
└──────┬───────────┘
│
▼
postings.ndjson (एक पंक्ति प्रति सार्वजनिक पद अवलोकन)
│
▼
गोदाम लोड + व्युत्पन्न वेग / बैकफिल / कार्य-मिक्स + अलर्ट
प्रत्येक चरण एक पाइथन मॉड्यूल है; नीचे सात कदम इसे निचले से ऊपर की ओर बनाते हैं।
कदम 1 — स्क्रेपलेस स्क्रेपिंग ब्राउज़र से कनेक्ट करें
कनेक्शन एकल वेबसोकेट URL है। इसे अपने एपीआई की, निकासी देश और एक सत्र जीवन-काल के समय से बनाएं, फिर इसे प्लेवेइट के connect_over_cdp को सौंपें। यह सिद्ध कनेक्शन आकार है — किसी अन्य अंत बिंदु को प्रतिस्थापित न करें:
python
import os
from urllib.parse import urlencode
from playwright.sync_api import sync_playwright
def scraping_browser_url(proxy_country="US", session_ttl=240):
params = urlencode({
"token": os.environ["SCRAPELESS_API_KEY"],
"sessionTTL": session_ttl,
"proxyCountry": proxy_country,
})
return f"wss://browser.scrapeless.com/api/v2/browser?{params}"
proxyCountry="US" आवासीय निकासी को संयुक्त राज्य अमेरिका में सुरक्षित करता है ताकि हर रिकॉर्ड बंडल को एक ही दृष्टिकोण से मापा जा सके — रनों के दौरान निकासी क्षेत्रों को मिलाकर एक पद इतिहास उत्पन्न होता है जिसका कोई अर्थ नहीं होता। sessionTTL=240 क्लाउड सत्र को चार मिनट तक जीवित रखता है, जो होमपेज को गर्म करने और फिर उसी सत्र में एक पृष्ठित खोज पृष्ठ लोड करने के लिए पर्याप्त है।
कदम 2 — एक सार्वजनिक नौकरी-खोज पृष्ठ रेंडर करें (पहले सत्र को गर्म करें)
भार वह विवरण: पहले साइट के होमपृष्ठ को लोड करें पहले, उसी सत्र के भीतर, लक्ष्य खोज URL पर जाने से पहले। गर्म होने से क्लाइंट-साइड स्थिति सुरक्षित होती है जिसकी उम्मीद एक सार्वजनिक खोज पृष्ठ करता है, इसलिए लक्ष्य पृष्ठ पूरी तरह से पेंट वापस आता है न कि आधा हाइड्रेटेड खोल के रूप में:
python
from playwright.sync_api import sync_playwright
def render_search_page(homepage_url: str, search_url: str,
proxy_country: str = "US") -> str:
"""गर्म होमपेज, फिर क्लाउड में सार्वजनिक नौकरी-खोज पृष्ठ को रेंडर करें।"""
```python
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(
scraping_browser_url(proxy_country=proxy_country)
)
context = browser.contexts[0] if browser.contexts else browser.new_context()
page = context.pages[0] if context.pages else context.new_page()
# 1) पहले होमपेज पर सत्र को गर्म करें।
page.goto(homepage_url, wait_until="domcontentloaded", timeout=60_000)
page.wait_for_timeout(1_500)
# 2) अब लक्षित सार्वजनिक खोज पृष्ठ लोड करें; ग्रिड हाइड्रेशन के बाद रंग लाता है।
page.goto(search_url, wait_until="networkidle", timeout=60_000)
page.wait_for_selector("[data-posting], article, li", timeout=20_000)
html = page.content()
browser.close()
return html
wait_until="networkidle" सूची ग्रिड को रंग लाने की अनुमति देता है इससे पहले कि page.content() DOM का स्नैपशॉट ले। wait_for_selector तब तक ब्लॉक करता है जब तक कम से कम एक पोस्टिंग कंटेनर मौजूद न हो, ताकि चरण 4 में एक्सट्रैक्टर कभी भी खाली पृष्ठ के खिलाफ न चले। proxy_country को वही बास्केट में परिभाषित क्षेत्र के साथ पिन करें, ताकि प्रदर्शित परिणाम वह दर्शाते हैं जो एक स्थानीय नौकरी का खोजकर्ता वास्तव में देखता है।
चरण 3 — कंपनी और स्रोत बास्केट परिभाषित करें
इंटेलिजेंस टीम इस फ़ाइल की मालिक है। इसे बोरिंग रखें — कंपनियाँ, प्रत्येक के लिए पढ़ने हेतु सार्वजनिक भर्ती सतहें, और मापने के लिए क्षेत्र। एक प्रविष्टि (कंपनी, स्रोत, क्षेत्र) प्रति जिसमें गर्म करने के लिए एक होमपेज और प्रदर्शित करने के लिए एक सार्वजनिक खोज URL हो:
yaml
# बास्केट.yaml
regions:
- US
companies:
- company: target_company_a
sources:
- source: company_careers
homepage: "https://careers.example-company-a.com/"
search:
US: "https://careers.example-company-a.com/jobs?country=US"
- source: public_aggregator
homepage: "https://jobs.example-aggregator.com/"
search:
US: "https://jobs.example-aggregator.com/search?q=engineering&loc=US"
- company: target_company_b
sources:
- source: company_careers
homepage: "https://careers.example-company-b.com/"
search:
US: "https://careers.example-company-b.com/openings"
प्रत्येक स्रोत के लिए सार्वजनिक HTML खोज पृष्ठ का उपयोग करें, न कि एक आंतरिक क्वेरी एंडपॉइंट जो एक साइट अपने रोबोट फ़ाइल में आरक्षित करती है। कई कंपनियों का ट्रैकिंग करने वाला एक बास्केट बिल्कुल इसी आकार में रहता है; गोदाम company पर जुड़ता है ताकि स्रोतों और क्षेत्रों के बीच भर्ती के संकेतों को संरेखित किया जा सके।
चरण 4 — मानक पोस्टिंग स्कीमा में निकालें
प्रत्येक स्रोत का DOM अलग है; गोदाम तालिका नहीं है। एक्सट्रैक्टर जो भी स्रोत प्रस्तुत करता है उसे हर बार उसी आकार में बदल देता है। स्कीमा जानबूझकर फर्मोग्राफिक है — कंपनी, भूमिका, स्थान, कार्यक्षेत्र, वरिष्ठता, पोस्टिंग तिथि, और एक स्थिर पोस्टिंग पहचानकर्ता। कोई नाम फ़ील्ड नहीं है, कोई संपर्क फ़ील्ड नहीं है, और कोई व्यक्तिगत-कार्यकाल फ़ील्ड नहीं है, और कभी नहीं होगा:
python
from dataclasses import dataclass, asdict
from datetime import datetime, timezone
from typing import Optional
from lxml import html as lxml_html
@dataclass
class PostingRecord:
company: str
source: str
region: str
posting_id: str # स्थिर प्रति-स्रोत आईडी या शीर्षक+स्थान का हैश
role_title: str
function: Optional[str] # "engineering" | "sales" | "ops" | ...
seniority: Optional[str] # "junior" | "mid" | "senior" | "staff" | None
location: Optional[str] # शहर / मेट्रो / "दूरस्थ"
posted_date: Optional[str] # ISO दिनांक स्ट्रिंग जो पृष्ठ प्रस्तुत करता है, या None
salary_band: Optional[str] # सार्वजनिक प्रतिस्पर्धी सीमा जहाँ पृष्ठ एक प्रकाशित करता है
captured_at: str # ISO-8601 UTC, पढ़ने के समय में लिखा गया
प्रति-स्रोत एक्सट्रैक्टर समान वापसी प्रकार में प्लग होते हैं। यह उदाहरण एक सामान्य कार्ड ग्रिड को पढ़ता है; स्रोत के अनुसार चयनकर्ताओं को स्वैप करें:
python
def extract_company_careers(html: str, company: str, source: str,
region: str) -> list[PostingRecord]:
doc = lxml_html.fromstring(html)
records: list[PostingRecord] = []
for card in doc.cssselect("[data-posting], article.job-card"):
title_el = card.cssselect(".job-title, h3")
loc_el = card.cssselect(".job-location, [data-location]")
date_el = card.cssselect("time, [data-posted]")
pay_el = card.cssselect(".salary, [data-comp]")
title = title_el[0].text_content().strip() if title_el else ""
if not title:
continue # गैर-पोस्टिंग कार्ड छोड़ दें; अनुपस्थित शीर्षक का मतलब असली सूची नहीं है
location = loc_el[0].text_content().strip() if loc_el else None
posted = (date_el[0].get("datetime") or date_el[0].text_content().strip()) if date_el else None
records.append(PostingRecord(
company=company,
source=source,
region=region,
posting_id=_posting_id(card, title, location),
role_title=title,
function=_classify_function(title),
seniority=_classify_seniority(title),
Here's the translated Hindi text:
python
स्थान=स्थान,
पोस्टेड_तिथि=पोस्टेड,
वेतन_band=pay_el[0].text_content().strip() अगर pay_el अन्यथा None,
कैप्चर_अत=datetime.now(timezone.utc).isoformat(),
))
रिटर्न रिकॉर्ड
वर्गीकरण सहायक Extractor में व्युत्पत्ति को बनाए रखते हैं, DOM में नहीं। वे एक भूमिका शीर्षक को एक मोटे कार्य और वरिष्ठता बैंड पर मैप करते हैं - इसमें कोई व्यक्तिगत डेटा शामिल नहीं है:
python
import hashlib
_FUNCTION_KEYWORDS = {
"इंजीनियरिंग": ("इंजीनियर", "डेवलपर", "sre", "प्लेटफार्म", "ml ", "डेटा "),
"बिक्री": ("बिक्री", "अकाउंट कार्यकारी", "अकाउंट प्रबंधक", "sdr"),
"मार्केटिंग": ("मार्केटिंग", "विकास", "ब्रांड", "सामग्री"),
"ऑपरेशंस": ("ऑपरेशंस", "आपूर्ति", "लॉजिस्टिक्स", "समर्थन"),
}
_SENIORITY_KEYWORDS = {
"स्टाफ": ("स्टाफ", "प्रधान", "प्रतिष्ठित"),
"सीनियर": ("सीनियर", "sr.", "लीड"),
"जूनियर": ("जूनियर", "jr.", "इंटर्न", "प्रवेश"),
}
def _classify(title: str, table: dict) -> Optional[str]:
low = title.lower()
for label, kws in table.items():
if any(kw in low for kw in kws):
return label
return None
def _classify_function(title: str) -> Optional[str]:
return _classify(title, _FUNCTION_KEYWORDS)
def _classify_seniority(title: str) -> Optional[str]:
return _classify(title, _SENIORITY_KEYWORDS) या "मध्यम"
def _posting_id(card, title: str, location: str | None) -> str:
native = card.get("data-posting-id") या card.get("id")
if native:
return native.strip()
# शीर्षक + स्थान का स्थिर हैश पुनः-प्रकाशित भूमिका को पहचानता है।
आधार = f"{title}|{location या ''}".lower().encode("utf-8")
return hashlib.sha1(basis).hexdigest()[:16]
चुनने की डिजाइन नोट्स:
- जब स्रोत उन्हें प्रदर्शित करता है तो
[data-posting]/data-*गुणों को प्राथमिकता दें। वे सौंदर्यात्मक कक्षा नाम के घुमावों को सहन करते हैं; कक्षाएँ जैसे.text-lg.font-semiboldहर रिलीज में बदलती हैं। - अस्तित्वहीन क्षेत्रों को नल के रूप में मानें। एक पोस्टिंग जिसमें कोई प्रकाशित
posted_dateयाsalary_bandनहीं है, फिर भी एक वैध अवलोकन है -Noneस्टोर करें और आगे बढ़ें। - नियुक्ति_आईडी को निश्चित रूप से व्युत्पन्न करें। शीर्षक + स्थान का हैश वही है जो वेयरहाउस को यह पहचानने देता है कि एक ही भूमिका पुनः प्रकट हो रही है - पिछले डेटा भरे जाने की पहचान का आधार - बिना कभी किसी व्यक्ति की पहचान किए।
अपने API कुंजी को मुक्त योजना पर प्राप्त करें: app.scrapeless.com
चरण 5 - बास्केट में चलें
प्रत्येक (कंपनी, स्रोत, क्षेत्र) प्रविष्टि एक स्वतंत्र रेंडर है। गर्म-फिर-लोड एक प्रविष्टि के लिए एक सत्र के भीतर चलती है, इसलिए बास्केट चलाना एक साधारण लूप है (या समानांतरता के लिए सीमा थ्रेड पूल, प्रति होस्ट तीन श्रमिकों पर सीमा):
python
import yaml
def load_basket(path: str = "basket.yaml") -> dict:
with open(path, encoding="utf-8") as f:
return yaml.safe_load(f)
def walk_basket(basket: dict):
"""प्रत्येक (कंपनी, स्रोत, क्षेत्र) प्रविष्टि के लिए पोस्टिंग रिकॉर्ड सूचियों को उत्पन्न करें।"""
for item in basket["companies"]:
for src in item["sources"]:
for region, search_url in src["search"].items():
html = render_search_page(
homepage_url=src["homepage"],
search_url=search_url,
proxy_country=region,
)
yield extract_company_careers(
html, item["company"], src["source"], region
)
एक बड़े बास्केट के लिए, render_search_page को concurrent.futures.ThreadPoolExecutor में लपेटें और श्रमिकों की संख्या को प्रति होस्ट तीन पर या नीचे रखें। प्रत्येक प्रविष्टि अपने स्वयं के सत्र को गर्म और लोड करती है, इसलिए समानांतरता श्रमिकों को जोड़कर बढ़ती है - साझा सत्र पर ध्यान केंद्रित करने की कोई आवश्यकता नहीं है।
चरण 6 - वेयरहाउस लोड के लिए NDJSON में स्ट्रीम करें
NDJSON में स्ट्रीम-लेखन करें ताकि पाइपलाइन एक मध्य-चाल रुकावट को बिना रिकॉर्ड खोए सहन कर सके। प्रत्येक पंक्ति एक सार्वजनिक पोस्टिंग अवलोकन है; फ़ाइल केवल-संलग्न है:
python
import json
from pathlib import Path
def append_records(records: list[PostingRecord], out_path: str = "postings.ndjson"):
Path(out_path).parent.mkdir(parents=True, exist_ok=True)
with open(out_path, "a", encoding="utf-8") as f:
for r in records:
f.write(json.dumps(asdict(r)) + "\n")
NDJSON सीधे Snowflake (COPY INTO ... FILE_FORMAT = (TYPE = JSON)), BigQuery (bq load --source_format=NEWLINE_DELIMITED_JSON), Redshift, ClickHouse, और DuckDB में लोड करता है। उस BI स्टैक को चुनें जिसका पहले से उपयोग किया जाता है; स्कीमा एक जैसा है।
चरण 7 - वेयरहाउस में स्कोरिंग मॉडल व्युत्पन्न करें
सिग्नल्स जिन पर इंटेलिजेंस टीम कार्य करती है, कच्ची पोस्टिंग नहीं हैं - वे व्युत्पन्न मैट्रिक्स हैं। हायरिंग वेलोसिटी, कार्य मिश्रण, और बैकफिल दबाव सभी वेयरहाउस में रहते हैं, पदावधि और पहचान के आधार पर समय के साथ गणना की जाती हैं, कभी स्क्रैपर में नहीं:
sql
-- हायरिंग वेलोसिटी: प्रत्येक कंपनी प्रति कार्य के लिए नए पोस्टिंग, अंतिम 7 दिनों की तुलना में पिछले 7
WITH obs AS (
SELECT company, function, posting_id,
Here is the translated text in Hindi:
sql
CAST(posted_date AS DATE) AS posted_date,
CAST(captured_at AS DATE) AS captured_date
FROM talent_postings
WHERE posted_date IS NOT NULL
),
windowed AS (
SELECT company, function,
COUNT(DISTINCT CASE WHEN posted_date >= CURRENT_DATE - 7 THEN posting_id END) AS reqs_last_7,
COUNT(DISTINCT CASE WHEN posted_date >= CURRENT_DATE - 14
AND posted_date < CURRENT_DATE - 7 THEN posting_id END) AS reqs_prior_7
FROM obs
GROUP BY company, function
)
SELECT company, function, reqs_last_7, reqs_prior_7,
reqs_last_7 - reqs_prior_7 AS velocity_delta
FROM windowed
ORDER BY velocity_delta DESC;
बैकफिल दबाव वही है posting_id एक कंपनी के लिए फिर से प्रकट होता है जब उसने दिखाना बंद कर दिया था - एक भूमिका-स्तरीय सिग्नल, जो पूरी तरह से पोस्टिंग पहचान और तिथियों से प्राप्त होता है:
sql
-- बैकफिल सिग्नल: एक posting_id जो गायब होता है फिर उसी कंपनी के लिए फिर से प्रकट होता है
SELECT company, posting_id, role_title,
COUNT(*) AS times_observed,
MIN(CAST(captured_at AS DATE)) AS first_seen,
MAX(CAST(captured_at AS DATE)) AS last_seen
FROM talent_postings
GROUP BY company, posting_id, role_title
HAVING MAX(CAST(captured_at AS DATE)) - MIN(CAST(captured_at AS DATE)) > 21
AND COUNT(DISTINCT CAST(captured_at AS DATE)) >= 2
ORDER BY company, times_observed DESC;
व्युत्पन्न पंक्तियों को उन उपभोक्ताओं के पास रूट करें जिन्हें इसकी आवश्यकता है:
- थreshhold से ऊपर वेलॉसिटी-डेल्टा → रणनीति टीम के लिए प्रतिस्पर्धात्मक-भर्ती अलर्ट।
- नई कार्यप्रणाली या नया मेट्रो प्रकट होना → कॉर्पोरेट विकास के लिए बाजार-विस्तार सूचना।
- एकल भूमिका पर उच्च बैकफिल संख्या → प्रतिभा-अधिग्रहण सिग्नल कि एक प्रतियोगी के पास उपयोग करने के लिए एक रिटेंशन गैप है।
व्युत्पत्ति क्वेरी संग्रह और निर्णय के बीच अनुबंध हैं। जब तक पोस्टिंग स्कीमा स्थिर रहता है, तब तक डाउनस्ट्रीम स्कोरिंग मॉडल, अलर्ट, और डैशबोर्ड कभी नहीं बदलते जब कोई स्रोत अपना DOM बदलता है - केवल स्टेप 4 में प्रति-स्रोत एक्सट्रैक्टर बदलता है।
आपको क्या वापस मिलता है
प्रत्येक सार्वजनिक पोस्टिंग अवलोकन के लिए एक NDJSON पंक्ति, इस तरह आकार दिया गया:
json
{
"company": "target_company_a",
"source": "company_careers",
"region": "US",
"posting_id": "a1b2c3d4e5f60718",
"role_title": "सीनियर प्लेटफ़ॉर्म इंजीनियर",
"function": "इंजीनियरिंग",
"seniority": "सीनियर",
"location": "ऑस्टिन, TX",
"posted_date": "<ISO दिनांक जो स्रोत प्रदर्शन करता है, या नल>",
"salary_band": "$180k–$220k",
"captured_at": "<ISO-8601 UTC टाइमस्टैंप लिखा गया जब पढ़ा गया>"
}
पैटर्न चलाने से ईमानदार अवलोकन:
- सत्र को गर्म करना ही ग्रिड को हल करता है। एक लक्षित खोज URL ठंडा लोड करने पर अक्सर एक आधा-पोषित शेल लौटाता है; पहले उसी सत्र में होमपेज लोड करना, फिर खोज पृष्ठ, एक्सट्रैक्टर के लिए आवश्यक पेंटेड कार्ड ग्रिड लौटाता है।
- रेंडर का समय चयनकर्ता की विशिष्टता से अधिक महत्वपूर्ण है। एक चयनकर्ता जो
networkidleसे पहले चलता है, एक खाली सूची लौटाता है। एक पोस्टिंग कंटेनर परwait_for_selectorवह गेट है जो एक्सट्रैक्टर को निर्धारणीय बनाता है। posting_idस्थिरता लोड-बेयरिंग फ़ील्ड है। जब कोई स्रोत एक स्थानीय आईडी खोलता है, तो उसका उपयोग करें; जब ऐसा नहीं होता है, तो शीर्षक-प्लस-स्थान हैश वह है जो पुनः पोस्ट की गई भूमिका को चलन के बीच जोड़ता है और बैकफिल क्वेरी को संचालित करता है।- पोस्टिंग तिथियां स्रोतों के बीच असंगत हैं। कुछ आईसो
datetimeविशेषता, कुछ संबंधी स्ट्रिंग ("3 दिन पहले"), कुछ कुछ नहीं प्रदर्शित करते हैं। जो पृष्ठ आपको देता है, उसे संग्रहीत करें और गोदाम परत में सापेक्ष तारों को सामान्य करें। - स्कीमा को फर्मोग्राफिक रखें। प्रति-स्रोत DOM भिन्न होते हैं; पोस्टिंग स्कीमा नहीं - और यह निर्माण द्वारा कोई व्यक्तिगत डेटा नहीं ले जाता है। परिवर्तनशीलता को एक्सट्रैक्टर कार्यों में धकेलें; स्कीमा को सपाट और PII-मुक्त रखें।
अनुपालन: यह एक फर्मोग्राफिक पाइपलाइन है, व्यक्तियों की पाइपलाइन नहीं
यह वह अनुभाग है जो अस्वीकरण को सच बनाता है न कि सजावटी। प्रतिभा बुद्धिमत्ता व्यक्तिगत डेटा के निकट स्थित है, इसलिए सीमा को डिज़ाइन में खींचना आवश्यक है, इसके बाद पैच नहीं करना है।
- कोई व्यक्तिगत डेटा एकत्र नहीं किया जाता है। स्कीमा में कंपनी, भूमिका शीर्षक, कार्य, वरिष्ठता बैंड, स्थान, पोस्टिंग तिथि, और सार्वजनिक वेतन रेंज शामिल हैं। इसमें नाम, ईमेल पते, फोन नंबर, व्यक्तिगत प्रोफाइल, या किसी की रोजगार इतिहास शामिल नहीं है। एक्सट्रैक्टर के लिए इनमें से कोई फ़ील्ड नहीं है, इसलिए कोई गोदाम में लीक नहीं हो सकता।
- विश्लेषण की एकाई कंपनी और भूमिका है, कभी भी व्यक्ति नहीं। "अट्रिशन सिग्नल" यहां एक भूमिका-स्तरीय बैकफिल पैटर्न का अर्थ है - एक ही पोस्टिंग कंपनी के लिए फिर से प्रकट होना - किसी व्यक्ति के नौकरी छोड़ने की ट्रैकिंग नहीं। "हायरिंग वेलॉसिटी" समय के साथ सार्वजनिक reqs की गिनती है, न कि एक सूची।
- कानूनी आधार और क्षेत्रीय कानून। सार्वजनिक पृष्ठों से प्राप्त एग्रीगेट, फर्मोग्राफिक भर्ती डेटा आमतौर पर सबसे संवेदनशील व्यक्तिगत डेटा श्रेणियों से बाहर होता है, लेकिन GDPR, CCPA और समान कानून किसी भी चीज़ पर लागू होते हैं जो किसी व्यक्ति की पहचान कर सकते हैं। हम डेटा सेट को फर्मोग्राफिक रखते हैं ताकि कानूनी आधार स्पष्ट हो; किसी भी दायरे के विस्तार के लिए, पहले वकील से कानूनी आधार की पुष्टि करें।
- साइट की शर्तों और रोबोट निर्देशों का सम्मान करें। सार्वजनिक HTML खोज पृष्ठों को प्रस्तुत करें जो एक साइट आगंतुकों के लिए प्रकाशित करती है; आंतरिक क्वेरी अंत बिंदुओं को लक्षित न करें जो एक साइट अपने रोबोट फ़ाइल में आरक्षित रखती है, और क्रॉल-डिले दिशानिर्देशों का सम्मान करें।
- सार्वजनिक नियोक्ता समीक्षा डेटा एग्रीगेट रहता है। जहां समीक्षा साइटें भावना के संदर्भ में योगदान करती हैं, वितरण-स्तरीय रेटिंग इकट्ठा करें — कभी भी व्यक्तिगत समीक्षक पहचान या किसी व्यक्ति से संबंधित समीक्षा पाठ नहीं।
एक एजेंट-चालित फ्रेमिंग के लिए समान संग्रह प्रारंभिक तत्वों के लिए, AI एजेंट उपयोग के मामले गाइड एक नौकरी-शिकारी एजेंट दिखाता है जो समान स्क्रैपिंग ब्राउज़र उपकरणों पर आधारित है।
निष्कर्ष: अपने प्रतिभा बाजार खुफिया पाइपलाइन का विस्तार करें
पाइपलाइन छह चरणों में सिमटती है: कंपनी-और-स्रोत बास्केट को परिभाषित करें → क्लाउड ब्राउज़र से कनेक्ट करें और सत्र को गर्म करें → प्रत्येक सार्वजनिक खोज पृष्ठ को अमेरिका से जुड़े पिन के साथ प्रस्तुत करें → फर्मोग्राफिक पोस्टिंग स्कीमा में निकालें → NDJSON में स्ट्रीम करें → वेयरहाउस में वेग, कार्य मिश्रण, और बैकफिल निकालें। प्रत्येक कदम इतना छोटा है कि पढ़ा जा सके; संयोजन कई कंपनियों को एकल दैनिक कार्यक्रम पर विभिन्न भर्ती सतहों के पार संभालता है।
अमेरिका से जुड़े पिन करें, लक्ष्य खोज पृष्ठ के लिए गर्म करें, प्रस्तुत करना → निकालने के पैटर्न का पालन करें, अनुपस्थित क्षेत्रों को आवश्यक मानें, और हर क्षेत्र को फर्मोग्राफिक रखें — कंपनी और भूमिका, कभी भी व्यक्ति नहीं।
क्या आप अपनी AI-संचालित डेटा पाइपलाइन बनाने के लिए तैयार हैं?
हमारे समुदाय में शामिल हों, एक मुफ्त योजना प्राप्त करें और डेवलपर्स के साथ जुड़ें जो प्रतिभा और प्रतिस्पर्धात्मक खुफिया पाइपलाइनों का निर्माण कर रहे हैं: डिस्कॉर्ड · टेलीग्राम।
app.scrapeless.com पर साइन अप करें मुफ्त स्क्रैपिंग ब्राउज़र रनटाइम के लिए और ऊपर दिए गए पैटर्न को उन कंपनियों, भर्ती सतहों और क्षेत्रों के अनुकूलित करें जिनकी पाइपलाइन को आवश्यकता है। मूल्य निर्धारण विवरण scrapeless.com/en/pricing पर; स्क्रैपिंग ब्राउज़र उत्पाद पृष्ठ scrapeless.com/en/product/scraping-browser पर है; पूर्ण कनेक्शन और प्रॉक्सी संदर्भ docs.scrapeless.com पर।
सामान्य प्रश्न
प्रश्न: क्या प्रतिभा बाजार खुफिया संग्रह करना कानूनी है, और व्यक्तिगत डेटा का क्या?
कानूनीता पूरी तरह से इस बात पर निर्भर करती है कि आप क्या इकट्ठा करते हैं। यह पाइपलाइन सार्वजनिक पृष्ठों से फर्मोग्राफिक, भूमिका-स्तरीय डेटा इकट्ठा करती है — नौकरी के शीर्षक, कार्य, स्थान, पोस्टिंग की संख्या, सार्वजनिक वेतन सीमा — और जानबूझकर कोई व्यक्तिगत डेटा नहीं इकट्ठा करती: न नाम, न संपर्क विवरण, न व्यक्तिगत रोजगार इतिहास। सार्वजनिक रूप से दृश्य डेटा सामान्य रूप से उपलब्ध होता है, लेकिन GDPR, CCPA, और समान कानून किसी भी चीज़ पर लागू होते हैं जो किसी व्यक्ति की पहचान कर सकते हैं, और साइट की सेवा शर्तें भी लागू होती हैं। स्कीमा को फर्मोग्राफिक बनाए रखना वो है जो कानूनी आधार को स्पष्ट रखता है; दायरा बढ़ाने से पहले वकील से परामर्श करें।
प्रश्न: क्या मुझे प्रॉक्सी की आवश्यकता है, और मुझे कौन सा देश पिन करना चाहिए?
हाँ। एग्रीगेटर्स और करियर पृष्ठें क्षेत्र और आईपी प्रतिष्ठा के द्वारा परिणामों को स्थानीयकृत करती हैं, इसलिए egress देश को उस क्षेत्र में पिन करें जिसे आप कनेक्शन यूआरएल पर proxyCountry के माध्यम से मापते हैं। अमेरिका-से-निकास अनुरोध क्षेत्र-गेटेड पृष्ठ पर एक फ़ॉलबैक या एक भू-निषेध वापस ला सकता है। Scrapeless आवासीय प्रॉक्सी 195 से अधिक देशों में सामान्य बास्केट को कवर करती हैं बिना स्टैक में एक अलग प्रॉक्सी प्रदाता लाए।
प्रश्न: एक खोज पृष्ठ खाली हो रहा है या एक एक्सेस चुनौती दिखा रहा है — मुझे साफ़ प्रस्तुतकरण कैसे मिले?
अमेरिकी आवासीय निकास को पिन करें और लक्ष्य लोड से पहले सत्र को गर्म करें: पहले उसी क्लाउड-ब्राउज़र सत्र के भीतर साइट के होमपेज पर जाएं, इसे बसने दें, फिर सार्वजनिक खोज यूआरएल पर जाएं और networkidle और एक पोस्टिंग-कंटेनर चयनकर्ता पर प्रतीक्षा करें। गर्म करना उस क्लाइंट-साइड स्थिति को स्थापित करता है जिसे खोज पृष्ठ उम्मीद करता है, इसलिए ग्रिड पूरी तरह से चित्रित होता है बजाय इसके कि आधा-हाइड्रेटेड शेल वापस आता है।
प्रश्न: जब एक स्रोत अपना DOM बदलता है तो क्या होता है?
केवल चरण 4 में स्रोत-विशिष्ट एक्सट्रैक्टर बदलता है। मानक पोस्टिंग स्कीमा, गोदाम तालिका, व्युत्पत्ति प्रश्न और अलर्टिंग नियम सभी अप्रभावित हैं। जब कोई स्रोत एक रिलीज़ भेजता है, तो अपने चयनकर्ताओं को फिर से जांचें और कसें; उपलब्ध होने पर data-* गुणों को प्राथमिकता दें; एक्सट्रैक्टर को अस्थिर परत के रूप में और स्कीमा को स्थिर परत के रूप में मानें।
प्रश्न: मैं बिना व्यक्तियों को ट्रैक किए भर्ती गति और बैकफिल कैसे प्राप्त कर सकता हूँ?
दोनों मेट्रिक पोस्टिंग की तारीखों और एक स्थिर posting_id से प्राप्त होते हैं, न कि लोगों से। गति हर कंपनी के लिए हर कार्य फ़ंक्शन के लिए समय विंडो पर खोले गए विभिन्न पोस्टिंग की गणना है। बैकफिल दबाव वही posting_id है जो विभिन्न रन में एक कंपनी के लिए फिर से प्रकट होता है। गणित गोदाम में (चरण 7) फर्मोग्राफिक अवलोकनों पर चलता है - कभी भी किसी व्यक्ति की पहचान या ट्रैक नहीं की जाती।
प्रश्न: क्या मैं कई कंपनियों और स्रोतों को समानांतर में चला सकता हूँ?
हां। प्रत्येक (कंपनी, स्रोत, क्षेत्र) प्रविष्टि अपने स्वयं के सत्र को गर्म करती और प्रस्तुत करती है, इसलिए ऑर्केस्ट्रेटर कार्यों को एक थ्रेड पूल में फैला देता है। काम करने वालों की संख्या को प्रत्येक होस्ट पर तीन या उससे कम रखें ताकि फैलाव विनम्र बना रहे; समानांतरता को कार्यकर्ताओं को जोड़कर बढ़ाया जाता है, सत्र साझा करने से नहीं।
प्रश्न: पाइपलाइन को कितनी बार चलाना चाहिए?
हर दिन भर्ती गति ट्रैकिंग के लिए मानक ताल है, क्योंकि पोस्टिंग कई दिनों की लय पर बदलती रहती हैं। धीमी गति वाले कार्य-मिक्स और विस्तार संकेतों के लिए साप्ताहिक ठीक है। चरण 7 में व्युत्पत्ति विंडो दैनिक कैप्चर मानती है; शेड्यूल को उस सबसे तेज संकेत के लिए संरेखित करें जिसे निर्णय परत वास्तव में उपभोग करती है।
स्क्रैपलेस में, हम केवल सार्वजनिक रूप से उपलब्ध डेटा का उपयोग करते हैं, जबकि लागू कानूनों, विनियमों और वेबसाइट गोपनीयता नीतियों का सख्ती से अनुपालन करते हैं। इस ब्लॉग में सामग्री केवल प्रदर्शन उद्देश्यों के लिए है और इसमें कोई अवैध या उल्लंघन करने वाली गतिविधियों को शामिल नहीं किया गया है। हम इस ब्लॉग या तृतीय-पक्ष लिंक से जानकारी के उपयोग के लिए सभी देयता को कोई गारंटी नहीं देते हैं और सभी देयता का खुलासा करते हैं। किसी भी स्क्रैपिंग गतिविधियों में संलग्न होने से पहले, अपने कानूनी सलाहकार से परामर्श करें और लक्ष्य वेबसाइट की सेवा की शर्तों की समीक्षा करें या आवश्यक अनुमतियाँ प्राप्त करें।



