Как создать скрепер We Work Remotely для публичных данных о вакансиях
TL;DR
Запустите парсер We Work Remotely с официальным публичным RSS-каналом, когда недавних объявлений о вакансиях достаточно.
Сохраняйте оригинальный URL вакансии и атрибутируйте ссылки на We Work Remotely, как это требует его страница канала.
Держите ограничения по местоположению объявления отдельно от факта, что роль является удаленной.
Используйте ограниченный, авторизованный рабочий процесс страницы деталей только тогда, когда канал не предоставляет необходимое поле.
Проверяйте записи перед их публикацией на доске объявлений или предоставлением их AI-помощнику.
Nstdata Crawl — это API для веб-краулинга для данных, готовых к LLM, который может обрабатывать слой сбора страниц; правила идентификации и соответствия вакансий остаются ответственностью вашего приложения.
Для чего нужен парсер We Work Remotely?
Парсер We Work Remotely конвертирует разрешенные объявления о вакансиях в записи, которые могут обрабатывать панели управления наймом, исследовательские конвейеры или помощники по поиску работы. Полезная запись связывает название и ограничение по местоположению с оригинальным объявлением, временем сбора и источником. Скачивание описания без этих полей затрудняет определение устаревших ролей или объяснение, почему помощник рекомендовал вакансию.
Самая простая реализация начинается с опубликованного канала платформы. Официальные инструкции We Work Remotely RSS предоставляют общий канал и каналы категорий и требуют атрибуции обратно к источнику. Это существенно отличная отправная точка от предположений о селекторах на странице категории.
Используйте Nstdata Crawl, когда ваш авторизованный рабочий процесс также нуждается в отрендеренных страницах деталей или контенте из других разрешенных источников. Держите прием канала и обогащение страниц как отдельные стадии, чтобы сбой в рендеринге не приводил к потере иначе действительных записей канала.
Что вам нужно перед сбором данных о работе?
Вам нужны Python, одобренное использование данных, официальный URL канала, место хранения и явный список необходимых полей. Пример канала ниже использует стандартную библиотеку Python и не требует учетной записи WWR или подписки на сторонний парсинг. Убедитесь, что ваше намеренное перепродажа соответствует требованиям источника, прежде чем превращать канал в публичный продукт.
Попробуйте Nstproxy Crawl - Начните Бесплатно Уже Сегодня
Поле
Значение
Правило принятия
source_url
Оригинальный URL деталей вакансии
Присутствует, HTTPS, ожидаемый исходный хост
source_id
GUID или URL канала
Стабилен в пределах этого источника
title
Заголовок канала
Не пустой; сохранить оригинальную формулировку
published_at
Временная метка издателя
Сохранять оригинальное значение наряду с разобранным временем
observed_at
Ваша временная метка сборки
UTC-временная метка, сгенерированная во время приема
region
Заявленное ограничение по найму
Сохранять отсутствующие значения, а не догадываться
description_html
Описание канала
Рассматривать как ненадежный контент источника
Не делайте вывод о диапазоне зарплат работодателя, политике виз или мировой пригодности из слова «удаленный». Описание может содержать ограничения, которые заголовок опускает. Держите эти поля допустимыми до тех пор, пока источник фактически не предоставит поддерживающий текст.
В чем разница между обнаружением канала и парсингом страниц?
Обнаружение канала получает недавние записи из управляемого издателем XML-документа; парсинг страниц читает HTML или отрендеренный документ сайта. Оба могут производить записи о вакансиях, но их охват и расходы на обслуживание различаются. Канал может быть удобным источником обнаружения, не представляя собой полные исторические архивы.
Во время исследования этой статьи общий канал WWR вернул элементы RSS с полями, включая title, link, guid, pubDate и description. Дополнительные поля присутствовали в наблюдаемом ответе, но клиент должен терпеть их отсутствие. Поздний ответ канала может содержать другое количество записей, поэтому никогда не кодируйте количество образцов как гарантию полноты.
Используйте валидацию структурированных данных, когда сопоставляете поля источника с вашей схемой вакансий. Для более широкой системы различайте сбор данных о рынке труда от классификации соответствия. Первое предоставляет доказательства. Второе интерпретирует доказательства и должно сохранять прослеживаемую причину для каждой полученной метки.
Как пошагово построить парсер?
Постройте парсер, получая официальный канал, нормализуя небольшой набор полей и сохраняя записи с их исходными идентификаторами. Следующие методы представляют различные потребности в сборе; это альтернативы или последовательные стадии, а не три способа принудительного доступа к одной и той же странице.
Метод 1: Используйте RSS для недавних объявлений
Шаг 1: Сохраните читатель канала
Сохраните следующее как wwr_feed.py. Читатель ограничивает размер загружаемого ответа, удаляет дубликаты ID и проверяет целевой хост перед принятием записи. Он не предполагает, что заголовок можно надежно разбить на поля компании и роли.
import json
import urllib.request
import xml.etree.ElementTree as ET
from datetime import datetime, timezone
from urllib.parse import urlsplit
url ="https://weworkremotely.com/remote-jobs.rss"request = urllib.request.Request(url, headers={"User-Agent":"JobFeedReader/1.0"})with urllib.request.urlopen(request, timeout=30)as response: payload = response.read(5_000_001)iflen(payload)>5_000_000:raise RuntimeError("Feed exceeds this reader's size limit")root = ET.fromstring(payload)observed = datetime.now(timezone.utc).isoformat()records, seen =[],set()for item in root.findall("./channel/item"): link =(item.findtext("link")or"").strip() parts = urlsplit(link)if parts.scheme !="https"or parts.hostname !="weworkremotely.com":continue identity =(item.findtext("guid")or link).strip() title =(item.findtext("title")or"").strip()ifnot title or identity in seen:continue seen.add(identity) records.append({"source_id": identity,"source_url": link,"title": title,"published_at": item.findtext("pubDate"),"observed_at": observed,"region": item.findtext("region"),"description_html": item.findtext("description")})ifnot records:raise RuntimeError("No accepted feed records; inspect the response")withopen("wwr-jobs.json","w", encoding="utf-8")as output: json.dump(records, output, ensure_ascii=False, indent=2)print("accepted records:",len(records))
Шаг 2: Запустите читатель
Запустите python wwr_feed.py в вашей рабочей директории. Тот же парсер использовался для обработки живого RSS-ответа во время подготовки этой статьи. Успешный запуск создает массив JSON и сообщает положительное количество принятых записей; точное число изменяется по мере обновления фида издателем.
Шаг 3: Проверьте одну принятыю запись
Откройте wwr-jobs.json и сравните название записи, URL и регион с оригинальным списком. Сохраняйте оригинальную ссылку на источник, где бы вы ни отображали результат. Если фид неполон для ваших целей, задокументируйте отсутствующее поле перед добавлением другого этапа сбора.
Метод 2: Добавить обогащение страницы с деталями, авторизованное
Шаг 1: Выберите отсутствующее поле
Выберите поле, которого действительно не хватает в фиде, такое как структурированный тип занятости. Проверьте, предоставляет ли страница машинно-читаемые свойства JobPosting перед тем, как написать визуальный селектор. Словарь схемы документирует значение поля; он не устанавливает, что WWR выдает каждое свойство на каждой странице.
Шаг 2: Проверьте одобренную страницу с деталями
Используйте Инструменты разработчика → Элементы, чтобы сравнить видимое содержимое страницы с любым JSON-LD скриптом. Запишите путь источника для поля и сохраните текст, использованный для его получения. Не публикуйте селектор, скопированный из старого учебника, не проверив разметку сегодня.
[Скриншот: Одобренная страница деталей работы, показывающая текст региона найма и соответствующее поле DOM или структурированных данных.]
Шаг 3: Храните обогащение отдельно
Присоедините результат деталей к записи фида по URL источника. Включите enrichment_status, enriched_at и ссылку на доказательства на уровне поля. Провал обогащения должен оставить действительную запись фида нетронутой и пометить только дополнительное поле как недоступное.
Метод 3: Добавьте Nstdata Crawl в поток сбора
Шаг 1: Получите текущую конфигурацию запроса
Откройте Nstdata Crawl Playground с страницы продукта Crawl, введите одобренный URL детали, выберите Markdown для обработки текста и проверьте сгенерированный запрос. Настройте рендеринг только тогда, когда необходимый контент требует JavaScript. Используйте ограничение по страницам и глубине для обнаружения, а не для автоматического обхода всего сайта вакансий.
Шаг 2: Подключите API-клиент
Установите nstdata-ai-crawl и установите NSTDATA_API_TOKEN в вашей локальной среде. Пример, приведенный ниже, требует вашего собственного токена и авторизации для APPROVED_PAGE_URL; он не выполнялся против WWR с клиентскими учетными данными. Имена SDK проверяются на соответствие текущему официальному пакету.
import os
from pathlib import Path
from nstdata_ai_crawl import NstDataClient, ScrapeRequestDto
token = os.environ["NSTDATA_API_TOKEN"]url = os.environ["APPROVED_PAGE_URL"]with NstDataClient(token)as client: result = client.submit_scrape_task_sync(ScrapeRequestDto( url=url, formats=["markdown"], onlyMainContent=True, timeout=60000))if result.success isnotTrueor result.status !="completed":raise RuntimeError("Page retrieval was not completed successfully")if result.data isNoneor result.data.truncated isTrue:raise RuntimeError("Missing or partial content requires review") text = result.data.get_markdown()ifnot text ornot text.strip():raise RuntimeError("No usable Markdown returned") Path("page.md").write_text(text, encoding="utf-8")print("Saved page.md; validate its content before downstream use")
Шаг 3: Принимайте только полезный контент
Подтвердите завершение задачи, проверьте результаты страницы и сравните возвращенный текст с целевым списком. Отклоните страницы, содержащие вызовы, пустые описания и обрезанный вывод, прежде чем передавать контент модели. Запишите ID задачи для диагностики, не записывая токен API.
Как Nstdata Crawl помогает с данными о работах?
Nstdata Crawl помогает, когда одобренный конвейер данных о работах нуждается в постоянном извлечении страниц и готовом к LLM текстом, выходящем за пределы фида. Это API веб-обработки для данных, готовых к LLM, расположенное между списком URL и вашим кодом нормализации. Обнаружение сайтов и рекурсивный обход могут расширить разрешённое семя в рамках явных границ. Рендеринг JavaScript может собирать контент, отсутствующий в исходном HTML. Сервис не решает, соответствует ли кандидат требованиям роли, или предоставляет разрешение на перепубликацию описания работы.
Выбор вывода: Markdown поддерживает обоснованные резюме, HTML поддерживает парсинг с учетом источника, а ссылки поддерживают обнаружение. JSON, PDF и визуальные артефакты служат различным потребностям на этапе рецензирования; запрос формата не подтверждает схему работы.
Управляемый доступ через прокси: Встроенная опция прокси Nstdata избегает отдельного прокси-хоста, порта, имени пользователя и пароля для стандартного управляемого запроса. Трафик прокси все равно может повлиять на стоимость; просмотрите текущие платежи за Crawl.
Ограниченная операция: Сначала отправьте небольшую работу, сохраните ID и результаты задач и повторите только восстанавливаемые сбои. Ваше приложение по-прежнему несет ответственность за дедубликацию, истечение срока действия и хранение.
Почему фиды вакансий становятся устаревшими или производят дубликаты?
Фиды вакансий становятся устаревшими, когда клиенты рассматривают окно непрерывного обнаружения как полный инвентаризационный список или путают повторные наблюдения с новыми объявлениями. Исчезновение записи из фида не доказывает, что работодатель закрыл вакансию. Храните first_seen, last_seen и отдельный статус доступности, чтобы неопределенность оставалась видимой.
Симптом
Вероятная причина
Исправление
Та же роль появляется несколько раз
Каждый опрос создает новую строку
Upsert по GUID фида или каноническому URL источника
“Всемирные” рекомендации неверные
Удаленный статус заменил ограничения по местоположению
Сохраните доказательства региона и требуйте явных правил соответствия
Нет записей после успешного ответа HTTP
Неожиданный документ, измененная лента или сбой парсера
Проверьте тип контента и корневой элемент; сохраните последний хороший набор данных
Резюме включает навигацию или инструкции
Исходный текст был принят без валидации
Ограничьте ввод текстом описания вакансии и изолируйте ненадежный контент
Используйте интерфейс XML ElementTree для демонстрации парсинга ленты, но соблюдайте ограничение по размеру ответа и избегайте принятия произвольно представленного пользователем XML. Экспортируйте только те поля, которые необходимы для вашего случая использования, и применяйте политику хранения к сохраненным описаниям.
Как запустить конвейер обработки данных о вакансиях?
Запустите конвейер с небольшим атрибутированным набором данных RSS, проверенным контрактом поля и явной политикой обновления. Сравните принятые записи с издателем перед добавлением обогащения и измерьте уровень дублирования, уровень отсутствующих полей и возраст записей. Успешная загрузка — это только начало надежной ленты вакансий.
Для более широкого сбора используйте ограниченный пакетный краулинг, чтобы отделить обнаружение URL от обработки страниц деталей. HTML и визуальные выходные данные Nstdata могут поддерживать последующий обзор сбоев извлечения.
В: Могу ли я собирать вакансии WWR без автоматизации браузера?
Да. Официальная публичная RSS лента может предоставлять недавние записи о вакансиях без безголового браузера. Проверьте требования к охвату и атрибуции перед использованием ее в продукте.
В: Содержит ли RSS лента все исторические вакансии?
Лента должна рассматриваться как окно недавнего открытия, если издатель явно не документирует историческую полноту. Храните разрешенные наблюдения с опорой на будущее, если вам нужна временная серия.
В: Может ли Nstdata Crawl гарантировать доступ к каждой странице вакансии?
Нет. Управляемый сервис извлечения остается подверженным доступности цели, ограничениям доступа, поведению рендеринга и вашей авторизации.
В: Нужно ли отсутствующие поля зарплаты заменять нулем?
Нет. Отсутствующая компенсация должна оставаться пустой или явно неизвестной. Ноль неверно подразумевает известное значение и искажает анализ.
В: Как доказать, что скребок работает?
Работающий скребок производит действительные записи с ссылками на источник, которые согласуются с вручную проверенной выборкой, сохраняет состояние обновления и сообщает о сбоях, не перезаписывая последний принятый набор данных.
Lena Zhou
Nov. 9th 2026
Сканируйте целые сайты одним API-запросом
Успешность 99,8% с рендерингом JavaScript
Получайте чистые данные для LLM в разных форматах
Преобразуйте любой сайт в Markdown, HTML, JSON, ссылки, PDF и другие форматы без управления инфраструктурой сканирования.