🎯 Trình duyệt đám mây tùy chỉnh, chống phát hiện được hỗ trợ bởi Chromium tự phát triển, thiết kế dành cho trình thu thập dữ liệu webtác nhân AI. 👉Dùng thử ngay
Quay lại blog

Tuyển Dụng Dựa Trên Dữ Liệu: Xây Dựng Nền Tảng Trí Tuệ Tài Năng Có Thể Mở Rộng Qua Web Scraping

Michael Lee
Michael Lee

Expert Network Defense Engineer

04-Jun-2026

Những điểm chính:

  • Thông tin thị trường nhân tài là một vấn đề công ty, không phải vấn đề cá nhân. Tín hiệu mà thúc đẩy chiến lược tuyển dụng, điểm chuẩn cạnh tranh và kế hoạch khu vực nằm trong các mẫu tổng hợp — bao nhiêu vai trò mà một công ty mở, trong những chức năng nào, ở những thành phố nào, và tốc độ ra sao — không bao giờ nằm trong các cá nhân cụ thể. Giữ đơn vị phân tích ở cấp công ty và vai trò, toàn bộ quy trình sẽ luôn tuân thủ pháp luật.
  • Các tín hiệu tuyển dụng công khai phân tán trên bốn mặt. Các tin tuyển dụng trên trang sự nghiệp của công ty và các trang tổng hợp, các phần tuyển dụng trên các trang web doanh nghiệp, các mục thông tin công ty trong các danh bạ nghề nghiệp, và các trang đánh giá nhà tuyển dụng mỗi cái mang một phần của bức tranh. Một mẫu kết xuất thu thập cả bốn; một sơ đồ chuẩn kết nối chúng với nhau.
  • Tốc độ tuyển dụng và số lượng thay thế là các chỉ số được suy luận, không phải là các trường thu thập. Bạn không thu thập "sự giảm nhân sự." Bạn thu thập ngày đăng tuyển và danh tính vai trò theo thời gian, sau đó suy luận tốc độ (các yêu cầu mới mỗi tuần) và áp lực thay thế (cùng một tiêu đề vai trò xuất hiện lại tại cùng một công ty) trong kho dữ liệu. DOM cung cấp cho bạn các quan sát; toán học cung cấp cho bạn tín hiệu.
  • Cuộc gọi kết xuất được định vị địa lý và đã được làm nóng phiên. Mỗi trang tìm kiếm công khai được kết xuất trong một trình duyệt đám mây với truy cập dân cư của Mỹ, thực thi JavaScript thực và một phiên đã được làm nóng — tải trang chính của trang web trước, sau đó là URL tìm kiếm mục tiêu. Quy trình sẽ gửi một URL cộng với một quốc gia và nhận lại một DOM hoàn chỉnh.
  • Dữ liệu cá nhân được giữ ngoài theo thiết kế. Quy trình này thu thập các tiêu đề công việc, phòng ban, vị trí, cấp bậc và số lượng bài đăng — không phải tên, chi tiết liên lạc, hoặc lịch sử làm việc của từng cá nhân. Phần tuân thủ bên dưới là hợp đồng chứng minh tuyên bố miễn trừ này là đúng.
  • Miễn phí để bắt đầu. Các tài khoản Scrapeless mới bao gồm thời gian chạy Trình duyệt thu thập miễn phí — đăng ký tại app.scrapeless.com.

Giới thiệu: Từ các bài đăng phân tán đến tín hiệu thị trường tuyển dụng

Các nhóm nhân tài và cạnh tranh có một điểm mù thường xuyên. Họ có thể cho bạn biết ai là đối thủ đang tuyển dụng hiện tại, nhưng không thể cho bạn biết đối thủ đó đang xây dựng cái gì — và câu trả lời đang ngồi ngay trước mắt trên các trang sự nghiệp công khai. Một công ty mở mười lăm yêu cầu kỹ sư nền tảng trong một quý đơn lẻ đang thông báo cho thị trường biết họ đang đầu tư ở đâu. Một công ty đăng lại cùng một vai trò kỹ sư nhân sự ba lần trong hai tháng đang thông báo cho thị trường rằng họ có một vấn đề thay thế. Đó là những tín hiệu cạnh tranh, và chúng được làm mới nhanh hơn bất kỳ báo cáo phân tích nào.

Thách thức cấu trúc không phải là "thu thập từ một bảng việc làm." Mà là điều hành một mạng lưới ổn định qua một nhóm công ty, qua một nhóm bề mặt tuyển dụng, qua một nhóm vùng miền — theo lịch trình, với những đảm bảo về độ chính xác giống nhau cho mỗi lần chạy. Các trang sự nghiệp công khai là các ứng dụng React và Next.js nơi mà danh sách xuất hiện sau khi nạp. Các trang tổng hợp định vị kết quả theo khu vực và danh tiếng IP. Mỗi yêu cầu phải vượt qua một lớp chống bot và quay trở lại dưới dạng một trang đã được kết xuất hoàn chỉnh, không phải là một vỏ trống. Và mỗi trang trong số đó chỉ cách một trình chọn cẩu thả khỏi một cái tên, một email, hoặc một hồ sơ cá nhân — dữ liệu mà quy trình này không bao giờ được chạm vào.

Hướng dẫn này đi qua kiến trúc và mã Python cho lớp thu thập của một quy trình thông tin thị trường nhân tài được xây dựng trên Trình duyệt thu thập Scrapeless. Kết xuất sử dụng kết nối trình duyệt đám mây đã được chứng minh: định vị truy cập của Mỹ, làm nóng phiên trên trang chính, sau đó tải trang tìm kiếm công việc công khai và trích xuất các bài đăng. Đầu ra là một dòng quan sát công ty và vai trò đã được chuẩn hóa cung cấp cho kho dữ liệu; đầu vào là nhóm công ty và nguồn do một nhà phân tích xác định. Đọc một lần để hiểu mẫu; sử dụng lại cho mỗi công ty bằng cách thay đổi bộ thu thập theo nguồn.


Những gì bạn có thể làm với nó

  • Điểm chuẩn tốc độ tuyển dụng. Theo dõi bao nhiêu vai trò mà một nhóm đối thủ mở mỗi tuần, theo chức năng, theo vùng miền — và xếp hạng ai đang gia tăng và ai đang giữ ổn định số lượng nhân viên.
  • Phân tích hỗn hợp chức năng. Một công ty chuyển đổi hỗn hợp bài đăng từ bán hàng sang kỹ thuật ML đang thông báo một sự chuyển hướng chiến lược. Giỏ bài đăng thể hiện sự thay đổi trước khi thông cáo báo chí thực hiện.
  • Tín hiệu mở rộng địa lý. Sự xuất hiện đầu tiên của các bài đăng trong một khu vực đô thị hoặc quốc gia mới là một chỉ báo dẫn đầu rằng một đối thủ đang mở thị trường. Định vị khu vực giúp tín hiệu có thể so sánh giữa các lần chạy.
  • Phát hiện thay thế và đăng lại. Cùng một tiêu đề vai trò xuất hiện lại tại cùng một công ty theo thời gian là một tín hiệu áp lực thay thế ở cấp độ vai trò — được suy luận từ danh tính và ngày đăng, không bao giờ từ việc theo dõi bất kỳ cá nhân nào.
  • Trí tuệ dải lương. Nơi mà các đăng tuyển công bố các khoảng tiền lương (bắt buộc ở một số tiểu bang của Mỹ), rổ tạo ra một tiêu chuẩn tiền lương công khai theo vai trò và khu vực cho một chức năng.
  • Bối cảnh tâm lý nhà tuyển dụng. Các phân phối đánh giá đã tổng hợp và ẩn danh từ các trang đánh giá nhà tuyển dụng công cộng cung cấp cái nhìn từ phía cầu về xu hướng thương hiệu tuyển dụng của đối thủ cạnh tranh.

Tại sao sử dụng Scrapeless Scraping Browser cho trí tuệ nhân lực

Scrapeless Scraping Browser là một trình duyệt đám mây tùy chỉnh, chống phát hiện, được thiết kế cho các trình thu thập dữ liệu web và các tác nhân AI. Đối với một pipeline trí tuệ thị trường nhân tài cụ thể, nó mang lại:

  • Proxy cư trú ở hơn 195 quốc gia, được gán cho từng phiên với mã quốc gia — địa lý xuất khẩu là một lĩnh vực cho mỗi khu vực bạn đo lường.
  • Kết xuất JavaScript trên đám mây. Các trang nghề nghiệp hiện đại và các trang tổng hợp là ứng dụng trang đơn; lưới danh sách xuất hiện sau khi làm ẩm. Trình duyệt đám mây trả về DOM sau khi vẽ, vì vậy các bộ chọn của bạn hoạt động dựa trên các thẻ thực, không phải một shell rỗng.
  • Khởi động phiên được tích hợp vào quy trình. Tải trang chính của trang web trước tiên trong cùng một phiên thiết lập cookie và trạng thái khách hàng mà một trang tìm kiếm công khai mong đợi, vì vậy việc tải mục tiêu tiếp theo sẽ trả về một kết xuất sạch sẽ.
  • Xử lý vân tay chống phát hiện trên máy chủ. Tín hiệu tác nhân người dùng, múi giờ, WebGL và canvas được ngẫu nhiên hóa trong đám mây theo phiên — không cần bảo trì plugin bí mật cục bộ và không có nhị phân trình duyệt trên máy của bạn.
  • Một khóa API cho toàn bộ pipeline. Kết xuất và xuất khẩu cư trú đều tính phí từ cùng một tài khoản Scrapeless; không cần nhà cung cấp proxy riêng biệt để kết nối.

Lấy khóa API của bạn trên gói miễn phí tại app.scrapeless.com.


Điều kiện tiên quyết

  • Python 3.10 hoặc mới hơn
  • Tài khoản và khóa API Scrapeless — đăng ký tại app.scrapeless.com
  • pip install playwright lxml pyyaml cssselect và một lần playwright install chromium (Chromium cục bộ chỉ nói giao thức; kết xuất chạy trên đám mây)
  • Làm quen với các bộ chọn CSS và một mục tiêu kho cơ bản (Snowflake, BigQuery, DuckDB hoặc Postgres)
  • Một tệp rổ công ty và nguồn

Kiến trúc pipeline trong cái nhìn tổng quan

Copy
basket.yaml                       (được xác định bởi nhà phân tích: công ty × nguồn × khu vực)
       │
       ▼
┌──────────────────┐
│   người điều hành   │  một nhiệm vụ cho mỗi (công ty, nguồn, khu vực); tỏa ra giới hạn
└──────┬───────────┘
       │
       ▼
┌──────────────────┐
│   Scrapeless     │  connect_over_cdp → làm ấm trang chính → tải URL tìm kiếm
│  (trình duyệt đám mây) │  xuất khẩu cư trú ở Mỹ, kết xuất JS, chống phát hiện
└──────┬───────────┘
       │  HTML kết xuất
       ▼
┌──────────────────┐
│   bộ chuẩn hóa     │  trình trích xuất theo nguồn → sơ đồ đăng tải chuẩn
└──────┬───────────┘
       │
       ▼
postings.ndjson           (một hàng cho mỗi quan sát đăng công khai)
       │
       ▼
tải kho + xác định vận tốc / lấp đầy / tỷ lệ chức năng + cảnh báo

Mỗi giai đoạn là một mô-đun Python; bảy bước dưới đây xây dựng nó từ dưới lên.


Bước 1 — Kết nối với Scrapeless Scraping Browser

Kết nối là một URL WebSocket duy nhất. Xây dựng nó từ khóa API của bạn cộng với quốc gia xuất khẩu và thời gian tồn tại phiên, sau đó đưa cho connect_over_cdp của Playwright. Đây là hình dạng kết nối đã được chứng minh — không thay thế một điểm cuối khác:

python Copy
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" gán xuất khẩu cư trú cho Hoa Kỳ giúp việc ghi lại mỗi đăng tuyển được đo từ cùng một góc nhìn — trộn lẫn các khu vực xuất khẩu giữa các lần chạy tạo ra một lịch sử đăng tuyển mà không có nghĩa gì. sessionTTL=240 giữ phiên đám mây hoạt động trong bốn phút, đủ thoải mái để làm ấm trang chính và sau đó tải một trang tìm kiếm phân trang trong cùng một phiên.


Bước 2 — Kết xuất một trang tìm kiếm việc làm công khai (làm ấm phiên trước)

Chi tiết quan trọng: tải trang chính của trang web trước tiên, trong cùng một phiên, trước khi điều hướng đến URL tìm kiếm mục tiêu. Làm ấm thiết lập trạng thái phía khách hàng mà một trang tìm kiếm công khai mong đợi, vì vậy trang mục tiêu sẽ trở lại với đầy đủ hình ảnh thay vì như một shell nửa làm ẩm:

python Copy
from playwright.sync_api import sync_playwright

def render_search_page(homepage_url: str, search_url: str,
                       proxy_country: str = "US") -> str:
    """Làm ấm trang chính, sau đó kết xuất trang tìm kiếm việc làm công khai trên đám mây."""
Copy
với sync_playwright() như p:
        trình duyệt = p.chromium.connect_over_cdp(
            scraping_browser_url(proxy_country=proxy_country)
        )
        ngữ cảnh = browser.contexts[0] nếu browser.contexts khác không thì browser.new_context()
        trang = context.pages[0] nếu context.pages khác không thì context.new_page()

        # 1) Khởi động phiên trên trang chủ trước.
        trang.goto(homepage_url, chờ_until="domcontentloaded", timeout=60_000)
        page.wait_for_timeout(1_500)

        # 2) Bây giờ tải trang tìm kiếm công khai mục tiêu; lưới sẽ được vẽ sau khi làm mát.
        trang.goto(search_url, chờ_until="networkidle", timeout=60_000)
        trang.wait_for_selector("[data-posting], article, li", timeout=20_000)

        html = trang.content()
        browser.close()
        return html

wait_until="networkidle" cho phép lưới danh sách hoàn thành việc vẽ trước khi page.content() chụp snap DOM. wait_for_selector chặn cho đến khi ít nhất một thùng chứa đăng tuyển có mặt, vì vậy bộ trích xuất trong Bước 4 không bao giờ chạy trên một trang trống. Ghim cùng proxy_country mà bạn xác định khu vực với trong giỏ, vì vậy các kết quả được render phản ánh những gì mà một người tìm việc địa phương thực sự thấy.


Bước 3 — Xác định giỏ công ty-và-nguồn

Đội ngũ tình báo sở hữu tệp này. Giữ cho nó nhàm chán — các công ty, các bề mặt tuyển dụng công khai để đọc cho mỗi công ty, và các khu vực để đo lường. Một mục cho mỗi (công ty, nguồn, khu vực) với cả một trang chủ để khởi động và một URL tìm kiếm công khai để render:

yaml Copy
# basket.yaml
khu vực:
  - Mỹ

công ty:
  - công ty: target_company_a
    nguồn:
      - nguồn: company_careers
        trang_chủ: "https://careers.example-company-a.com/"
        tìm kiếm:
          Mỹ: "https://careers.example-company-a.com/jobs?country=US"
      - nguồn: public_aggregator
        trang_chủ: "https://jobs.example-aggregator.com/"
        tìm kiếm:
          Mỹ: "https://jobs.example-aggregator.com/search?q=engineering&loc=US"
  - công ty: target_company_b
    nguồn:
      - nguồn: company_careers
        trang_chủ: "https://careers.example-company-b.com/"
        tìm kiếm:
          Mỹ: "https://careers.example-company-b.com/openings"

Sử dụng trang tìm kiếm HTML công khai cho mỗi nguồn, không phải là một điểm cuối truy vấn nội bộ mà một trang dự trữ trong tệp robots của nó. Một giỏ theo dõi hàng chục công ty sống trong chính hình dạng này; kho sẽ kết hợp trên company để căn chỉnh tín hiệu tuyển dụng giữa các nguồn và khu vực.


Bước 4 — Trích xuất vào schema đăng tuyển chuẩn

DOM của mỗi nguồn là khác nhau; bảng kho không như vậy. Bộ trích xuất biến những gì một nguồn render thành cùng một hình dạng mỗi lần. Schema là cố ý firmographic — công ty, vai trò, địa điểm, chức năng, cấp bậc, ngày đăng, và một định danh đăng ổn định. Không có trường tên, không có trường liên hệ, và không có trường thời gian cá nhân, và sẽ không bao giờ có:

python Copy
từ dataclasses nhập khẩu dataclass, asdict
từ datetime nhập khẩu datetime, timezone
từ typing nhập khẩu Optional
từ lxml nhập khẩu html như lxml_html

@dataclass
class PostingRecord:
    công ty: str
    nguồn: str
    khu vực: str
    posting_id: str                 # id ổn định theo nguồn hoặc một băm của title+location
    role_title: str
    chức năng: Optional[str]          # "engineering" | "sales" | "ops" | ...
    cấp bậc: Optional[str]         # "junior" | "mid" | "senior" | "staff" | None
    địa điểm: Optional[str]          # thành phố / metro / "từ xa"
    posted_date: Optional[str]       # chuỗi ngày ISO mà trang render, hoặc None
    salary_band: Optional[str]       # phạm vi lương công khai nơi trang xuất bản một cái
    captured_at: str                 # ISO-8601 UTC, ghi lại tại thời gian đọc

Các bộ trích xuất theo nguồn cắm vào cùng một kiểu trả về. Ví dụ này đọc một lưới thẻ chung; hoán đổi các bộ chọn theo nguồn:

python Copy
def extract_company_careers(html: str, company: str, source: str,
                            region: str) -> list[PostingRecord]:
    doc = lxml_html.fromstring(html)
    records: list[PostingRecord] = []

    cho card trong 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() nếu title_el khác không thì ""
        nếu không có title:
            tiếp tục  # bỏ qua các thẻ không đăng; thiếu tiêu đề có nghĩa là không phải là một danh sách thực sự

        location = loc_el[0].text_content().strip() nếu loc_el khác không thì None
        posted = (date_el[0].get("datetime") hoặc date_el[0].text_content().strip()) nếu date_el khác không thì None

        records.append(PostingRecord(
            công ty=company,
            nguồn=source,
            khu vực=region,
            posting_id=_posting_id(card, title, location),
            role_title=title,
            chức năng=_classify_function(title),
            cấp bậc=_classify_seniority(title),
vi Copy
location=location,
            posted_date=posted,
            salary_band=pay_el[0].text_content().strip() if pay_el else None,
            captured_at=datetime.now(timezone.utc).isoformat(),
        ))
    return records

Các trợ giúp phân loại giữ lại sự suy diễn trong bộ trích xuất, không phải trong DOM. Chúng ánh xạ một tiêu đề vai trò tới một chức năng thô và băng cấp bậc — không có dữ liệu cá nhân nào liên quan:

python Copy
import hashlib

_FUNCTION_KEYWORDS = {
    "kỹ thuật": ("kỹ sư", "nhà phát triển", "sre", "nền tảng", "ml ", "dữ liệu "),
    "bán hàng": ("bán hàng", "chuyên viên khách hàng", "quản lý tài khoản", "sdr"),
    "tiếp thị": ("tiếp thị", "tăng trưởng", "thương hiệu", "nội dung"),
    "vận hành": ("vận hành", "cung ứng", "hậu cần", "hỗ trợ"),
}
_SENIORITY_KEYWORDS = {
    "nhân viên": ("nhân viên", "chính", "xuất sắc"),
    "cao cấp": ("cao cấp", "sr.", "trưởng nhóm"),
    "trẻ": ("trẻ", "jr.", "thực tập sinh", "mới vào"),
}

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) or "trung bình"

def _posting_id(card, title: str, location: str | None) -> str:
    native = card.get("data-posting-id") or card.get("id")
    if native:
        return native.strip()
    # Băm ổn định của tiêu đề + vị trí xác định một vai trò được đăng lại xuyên suốt các lần chạy.
    basis = f"{title}|{location or ''}".lower().encode("utf-8")
    return hashlib.sha1(basis).hexdigest()[:16]

Ghi chú thiết kế bộ chọn:

  • Ưu tiên [data-posting] / thuộc tính data-* khi nguồn cung cấp chúng. Chúng tồn tại qua việc xoay vòng tên lớp thẩm mỹ; các lớp như .text-lg.font-semibold thay đổi trong mỗi bản phát hành.
  • Xử lý các trường vắng mặt như nullable. Một thông báo không có posted_date hay salary_band được công bố vẫn là một quan sát hợp lệ — lưu None và tiếp tục.
  • Suy diễn posting_id một cách xác định. Băm của title + location là thứ cho phép kho nhận diện vai trò tương tự tái xuất hiện xuyên suốt các lần chạy — cơ sở để phát hiện số lượng đăng lại — mà không bao giờ xác định một cá nhân.

Lấy khóa API của bạn trên gói miễn phí: app.scrapeless.com


Bước 5 — Đi bộ qua giỏ hàng

Mỗi mục (công ty, nguồn, khu vực) là một kết xuất độc lập. Chạy ấm rồi tải bên trong một phiên cho mỗi mục, vì vậy việc đi bộ qua giỏ hàng là một vòng lặp đơn giản (hoặc một bể luồng giới hạn cho sự song song, giới hạn ở ba công nhân mỗi máy chủ):

python Copy
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):
    """Trả về danh sách PostingRecord cho mỗi mục (công ty, nguồn, khu vực)."""
    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
                )

Đối với một giỏ lớn hơn, bọc render_search_page trong một concurrent.futures.ThreadPoolExecutor và giữ số lượng công nhân ở hoặc dưới ba trên mỗi máy chủ. Mỗi mục làm ấm và tải phiên riêng của nó, vì vậy sự song song tăng lên bằng cách thêm công nhân — không có phiên nào chung để tranh cãi.


Bước 6 — Dòng sang NDJSON để tải vào kho

Ghi dòng sang NDJSON để ống dẫn sống sót qua một sự gián đoạn giữa chừng mà không mất thông tin. Mỗi hàng là một quan sát về thông báo công khai; tệp này chỉ thêm vào:

python Copy
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 tải trực tiếp vào Snowflake (COPY INTO ... FILE_FORMAT = (TYPE = JSON)), BigQuery (bq load --source_format=NEWLINE_DELIMITED_JSON), Redshift, ClickHouse, và DuckDB. Chọn bất kỳ cái nào mà ngăn BI đã sử dụng; sơ đồ là giống nhau.


Bước 7 — Suy diễn mô hình điểm số trong kho

Các tín hiệu mà nhóm thông minh hành động không phải là các thông báo thô — chúng là các chỉ số suy diễn. Tốc độ tuyển dụng, sự phân bổ chức năng, và áp lực tái tuyển dụng đều sống trong kho, được tính toán từ ngày đăng và danh tính theo thời gian, không bao giờ trong bộ lấy mẫu:

sql Copy
-- Tốc độ tuyển dụng: số lượng thông báo mới theo công ty theo chức năng, 7 ngày qua so với 7 ngày trước
WITH obs AS (
  SELECT company, function, posting_id,
sql Copy
CAST(posted_date AS DATE) AS posted_date,
         CAST(captured_at AS DATE) AS captured_date
  TỪ talent_postings
  NƠI posted_date IS NOT NULL
),
windowed AS (
  CHỌN công ty, chức năng,
    COUNT(DISTINCT CASE KHI posted_date >= CURRENT_DATE - 7  THÌ posting_id KẾT THÚC) AS reqs_last_7,
    COUNT(DISTINCT CASE KHI posted_date >= CURRENT_DATE - 14
                         VÀ posted_date <  CURRENT_DATE - 7  THÌ posting_id KẾT THÚC) AS reqs_prior_7
  TỪ obs
  NHÓM THEO công ty, chức năng
)
CHỌN công ty, chức năng, reqs_last_7, reqs_prior_7,
       reqs_last_7 - reqs_prior_7 AS velocity_delta
TỪ windowed
ORDER BY velocity_delta DESC;

Áp lực bổ sung là việc cùng một posting_id xuất hiện trở lại cho một công ty sau khi nó đã ngừng hiển thị — một tín hiệu ở cấp độ vai trò, được suy ra hoàn toàn từ danh tính và ngày tháng đăng bài:

sql Copy
-- Tín hiệu bổ sung: một posting_id biến mất rồi xuất hiện trở lại cho cùng một công ty
CHỌN công ty, posting_id, vai_trò,
       COUNT(*)                       AS times_observed,
       MIN(CAST(captured_at AS DATE)) AS first_seen,
       MAX(CAST(captured_at AS DATE)) AS last_seen
TỪ talent_postings
NHÓM THEO công ty, posting_id, vai_trò
HAVING MAX(CAST(captured_at AS DATE)) - MIN(CAST(captured_at AS DATE)) > 21
   VÀ COUNT(DISTINCT CAST(captured_at AS DATE)) >= 2
ORDER BY công ty, times_observed DESC;

Chuyển các hàng đã suy luận đến người tiêu dùng cần chúng:

  • Mức độ tăng tốc vượt quá ngưỡng → cảnh báo tuyển dụng cạnh tranh cho nhóm chiến lược.
  • Chức năng mới hoặc metro mới xuất hiện → thông báo mở rộng thị trường cho phát triển doanh nghiệp.
  • Số lượng bổ sung cao cho một vai trò đơn lẻ → tín hiệu thu hút tài năng rằng một đối thủ có khoảng trống duy trì cần khai thác.

Các truy vấn suy luận là hợp đồng giữa việc thu thập và quyết định. Chỉ cần cấu trúc bài đăng vẫn ổn định, các mô hình điểm số, cảnh báo và bảng điều khiển phía hạ nguồn sẽ không thay đổi khi một nguồn thay đổi DOM của nó — chỉ có bộ trích xuất theo nguồn trong Bước 4 thay đổi.


Những gì bạn nhận lại

Một hàng NDJSON cho mỗi quan sát bài đăng công khai, được hình thành như sau:

json Copy
{
  "công_ty": "target_company_a",
  "nguồn": "company_careers",
  "khu_vực": "US",
  "posting_id": "a1b2c3d4e5f60718",
  "vai_trò": "Kỹ sư Nền tảng Cấp cao",
  "chức_năng": "kỹ thuật",
  "cấp_bậc": "cấp cao",
  "địa_chỉ": "Austin, TX",
  "ngày_đăng": "<ngày ISO mà nguồn hiển thị, hoặc null>",
  "mức_lương": "$180k–$220k",
  "captured_at": "<thời gian dấu thời gian UTC ISO-8601 được viết khi đọc>"
}

Những quan sát chân thực từ việc chạy mẫu:

  • Khởi động phiên là cái khiến lưới được giải quyết. Một URL tìm kiếm mục tiêu được tải một cách lạnh thường trả về một vỏ shell nửa đủ; tải trang chính trước trong cùng một phiên, sau đó là trang tìm kiếm, trả về lưới thẻ được vẽ mà bộ trích xuất cần.
  • Thời gian hiển thị quan trọng hơn độ chính xác của bộ chọn. Một bộ chọn chạy trước networkidle trả về một danh sách rỗng. wait_for_selector trên một container bài đăng là cách mà làm cho bộ trích xuất trở nên xác định.
  • Sự ổn định của posting_id là trường chịu lực. Khi một nguồn tiết lộ mã định danh gốc, hãy sử dụng nó; khi không, hàm băm tiêu đề-cộng-vị trí là thứ liên kết một vai trò được đăng lại qua các lần chạy và cung cấp lực cho truy vấn bổ sung.
  • Ngày đăng bài không đồng nhất giữa các nguồn. Một số hiển thị thuộc tính datetime ISO, một số là chuỗi tương đối ("3 ngày trước"), một số không gì cả. Lưu những gì trang cung cấp cho bạn và chuẩn hóa các chuỗi tương đối trong lớp kho dữ liệu.
  • Giữ nghiêm ngặt cấu trúc định danh công ty. Các DOM theo nguồn khác nhau; cấu trúc bài đăng thì không — và nó không chứa dữ liệu cá nhân theo thiết kế. Đẩy sự biến đổi vào các chức năng trích xuất; giữ cho cấu trúc phẳng và không có dữ liệu cá nhân.

Tuân thủ: đây là một quy trình định danh công ty, không phải quy trình cá nhân

Đây là phần làm cho bản tuyên bố trở thành sự thật chứ không phải chỉ là trang trí. Sự thông minh về tài năng nằm cạnh dữ liệu cá nhân, vì vậy ranh giới phải được vẽ trong thiết kế, không phải vá lại sau này.

  • Không có dữ liệu cá nhân nào được thu thập. Cấu trúc chứa thông tin về công ty, tiêu đề vai trò, chức năng, cấp bậc, địa chỉ, ngày đăng và phạm vi lương công khai. Nó không chứa tên, địa chỉ email, số điện thoại, hồ sơ cá nhân hoặc lịch sử việc làm của bất kỳ ai. Bộ trích xuất không có trường cho chúng, vì vậy không có gì có thể rò rỉ vào kho dữ liệu.
  • Đơn vị phân tích là công ty và vai trò, không bao giờ là cá nhân. "Tín hiệu thôi việc" ở đây nghĩa là một mẫu bổ sung ở cấp độ vai trò — cùng một bài đăng xuất hiện trở lại cho một công ty — không phải theo dõi bất kỳ ai rời khỏi công việc. "Tốc độ tuyển dụng" là số yêu cầu công cộng theo thời gian, không phải là danh sách.
  • Cơ sở hợp pháp và luật vùng miền. Dữ liệu tuyển dụng tổng hợp, có liên quan đến đặc điểm công ty từ các trang công khai thường nằm ngoài các loại dữ liệu cá nhân nhạy cảm nhất, nhưng GDPR, CCPA và các chế độ tương đương vẫn áp dụng cho bất cứ điều gì có thể xác định một người. Chúng tôi giữ dữ liệu tổng hợp chính vì lý do đó, để cơ sở hợp pháp trở nên rõ ràng; đối với bất kỳ sự mở rộng phạm vi nào, hãy xác nhận cơ sở pháp lý với luật sư trước.
  • Tôn trọng điều khoản trang và chỉ thị của robot. Hiển thị các trang tìm kiếm HTML công khai mà một trang web công bố cho khách truy cập; không nhắm vào các điểm cuối truy vấn nội bộ mà một trang lưu trữ trong tệp robots của nó, và tôn trọng hướng dẫn crawl-delay.
  • Dữ liệu đánh giá nhà tuyển dụng công khai vẫn ở dạng tổng hợp. Ở những nơi các trang đánh giá đóng góp ngữ cảnh cảm xúc, thu thập đánh giá mức phân phối — không bao giờ lấy danh tính của người đánh giá cá nhân hoặc văn bản đánh giá liên kết với một người.

Đối với một cái nhìn điều hành về những nguyên tắc thu thập tương tự, hướng dẫn trường hợp sử dụng AI agent cho thấy một đại lý săn việc được xây dựng dựa trên các công cụ Scraping Browser giống hệt.


Kết luận: mở rộng quy trình trí tuệ thị trường tài năng của bạn

Quy trình được rút gọn thành sáu bước: xác định giỏ công ty và nguồn → kết nối với trình duyệt đám mây và khởi động phiên → hiển thị mỗi trang tìm kiếm công khai với đầu ra của Mỹ được ghim → trích xuất vào một sơ đồ đăng tuyển firmographic → truyền phát đến NDJSON → suy diễn tốc độ, sự pha trộn chức năng và bổ sung vào kho. Mỗi bước đủ nhỏ để đọc; cấu trúc xử lý hàng chục công ty trên nhiều bề mặt tuyển dụng trong một lịch trình hàng ngày duy nhất.

Ghim đầu ra của Mỹ, khởi động trang chính trước khi trang tìm kiếm mục tiêu bên trong một phiên, theo mẫu render → extract, coi các trường không có giá trị là nullable, và giữ mọi trường firmographic — công ty và vai trò, không bao giờ là cá nhân.


Sẵn sàng để Xây Dựng Quy Trình Dữ Liệu AI của Bạn?

Tham gia cộng đồng của chúng tôi để nhận kế hoạch miễn phí và kết nối với các nhà phát triển đang xây dựng quy trình trí tuệ thị trường tài năng và cạnh tranh: Discord · Telegram.

Đăng ký tại app.scrapeless.com để có thời gian chạy Scraping Browser miễn phí và điều chỉnh các mẫu trên cho các công ty, bề mặt tuyển dụng và khu vực mà quy trình cần. Chi tiết giá cả tại scrapeless.com/en/pricing; trang sản phẩm Scraping Browser có tại scrapeless.com/en/product/scraping-browser; tham khảo đầy đủ kết nối và proxy tại docs.scrapeless.com.


Câu hỏi thường gặp

H: Việc thu thập trí tuệ thị trường tài năng có hợp pháp không, và còn về dữ liệu cá nhân thì sao?

Tính hợp pháp hoàn toàn phụ thuộc vào những gì bạn thu thập. Quy trình này thu thập dữ liệu firmographic, ở mức vai trò từ các trang công khai — danh hiệu công việc, chức năng, vị trí, số lượng đăng tải, khoảng lương công khai — và cố ý không thu thập bất kỳ dữ liệu cá nhân nào: không có tên, không có thông tin liên hệ, không có lịch sử việc làm cá nhân. Dữ liệu công khai nhìn thấy thường có thể truy cập, nhưng GDPR, CCPA và các luật tương đương vẫn áp dụng cho bất cứ điều gì có thể xác định một người, và các điều khoản dịch vụ của trang web áp dụng trên toàn bộ. Giữ cho sơ đồ là firmographic là điều giữ cho cơ sở hợp pháp rõ ràng; hãy tham khảo luật sư trước khi mở rộng phạm vi.

H: Tôi có cần một proxy không, và nên ghim tại quốc gia nào?

Có. Các bên tổng hợp và các trang tìm việc địa phương hóa kết quả theo vùng và uy tín IP, vì vậy hãy ghim quốc gia đầu ra đến khu vực mà bạn đo lường thông qua proxyCountry trên URL kết nối. Một yêu cầu đầu ra tại Mỹ tới một trang bị hạn chế khu vực có thể trả về một dự phòng hoặc một geo-block. Scraping residential proxies tại 195+ quốc gia bao phủ giỏ điển hình mà không cần đưa một nhà cung cấp proxy riêng biệt vào cấu trúc.

H: Một trang tìm kiếm hiển thị trống hoặc gặp thử thách truy cập — làm thế nào để tôi có được một bản hiển thị sạch?

Ghim đầu ra tại Mỹ và khởi động phiên trước khi tải mục tiêu: điều hướng đến trang chính của trang web trước trong cùng một phiên trình duyệt đám mây, để nó định hình, sau đó điều hướng đến URL tìm kiếm công khai và chờ trên networkidle cộng với một bộ chọn chứa nội dung đăng. Khởi động thiết lập trạng thái phía máy khách mà trang tìm kiếm mong đợi, vì vậy lưới sẽ được tô đầy thay vì trả về một vỏ rỗng chưa hoàn chỉnh.

H: Điều gì xảy ra khi một nguồn thay đổi DOM của nó?
Chỉ có bộ trích xuất theo nguồn trong Bước 4 là thay đổi. Lược đồ đăng bài chuẩn, bảng kho, các truy vấn suy diễn và các quy tắc cảnh báo đều không bị ảnh hưởng. Hãy kiểm tra lại và thu hẹp các bộ chọn của bạn khi một nguồn cung cấp một bản phát hành; ưu tiên các thuộc tính data-* khi có sẵn; coi bộ trích xuất như là lớp biến động và lược đồ như là lớp ổn định.

H: Làm thế nào để tôi suy diễn tốc độ tuyển dụng và bù đắp mà không theo dõi từng cá nhân?

Cả hai chỉ số đều lấy từ ngày đăng bài và một posting_id ổn định, không phải từ con người. Tốc độ là số lượng đăng bài riêng biệt được mở cho mỗi công ty theo từng chức năng trong một khoảng thời gian. Áp lực bù đắp là cùng một posting_id xuất hiện lại cho một công ty qua các lần chạy. Phép toán diễn ra trong kho (Bước 7) dựa trên các quan sát firmographic — không có cá nhân nào được xác định hoặc theo dõi.

H: Tôi có thể chạy nhiều công ty và nguồn song song không?

Có. Mỗi (công ty, nguồn, khu vực) sẽ khởi tạo và xử lý phiên của riêng nó, vì vậy bộ điều phối sẽ phân bổ các tác vụ trong một nhóm luồng. Giữ số lượng nhân viên ở mức hoặc dưới ba mỗi máy chủ để việc phân bổ được lịch sự; sự song song tăng lên bằng cách thêm công nhân, không phải bằng cách chia sẻ một phiên.

H: Pipeline nên chạy bao lâu một lần?

Hàng ngày là nhịp độ chuẩn cho việc theo dõi tốc độ tuyển dụng, vì các bài đăng thay đổi theo nhịp độ nhiều ngày. Hàng tuần là đủ cho các tín hiệu chức năng chậm hơn và mở rộng. Các khoảng thời gian suy diễn trong Bước 7 giả định việc thu thập hàng ngày; hãy điều chỉnh lịch trình theo tín hiệu nhanh nhất mà lớp quyết định thực sự tiêu thụ.

Tại Scrapless, chúng tôi chỉ truy cập dữ liệu có sẵn công khai trong khi tuân thủ nghiêm ngặt các luật, quy định và chính sách bảo mật trang web hiện hành. Nội dung trong blog này chỉ nhằm mục đích trình diễn và không liên quan đến bất kỳ hoạt động bất hợp pháp hoặc vi phạm nào. Chúng tôi không đảm bảo và từ chối mọi trách nhiệm đối với việc sử dụng thông tin từ blog này hoặc các liên kết của bên thứ ba. Trước khi tham gia vào bất kỳ hoạt động cạo nào, hãy tham khảo ý kiến ​​cố vấn pháp lý của bạn và xem xét các điều khoản dịch vụ của trang web mục tiêu hoặc có được các quyền cần thiết.

Bài viết phổ biến nhất

Danh mục