Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
wxpath — wxpath - декларативный веб-скрапинг с XPath; язык веб-запросов (WQL) | Kitploit
Инструменты/GitHubGitHub/rodricios/wxpath
OSINT (Разведка открытых источников)РазведкаЭксфильтрация данныхСбор информацииВеб-безопасностьКраулер
GitHubrodricios/wxpath

wxpath

wxpath - декларативный веб-скрапинг с XPath; язык веб-запросов (WQL)

Репозиторий
111622 месяцев назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

wxpath — декларативный обход веб-графа с помощью XPath

Python 3.10+ Documentation Status

НОВИНКА: TUI — интерактивный терминальный интерфейс (на основе Textual) для тестирования выражений wxpath и экспорта данных.

Скриншот демо TUI wxpath

Установка

Требуется Python 3.10+.

root@kitploit:~
pip install wxpath
# Для поддержки TUI:
pip install "wxpath[tui]"
# Быстрый запуск TUI через uv:
uvx --from "wxpath[tui]" wxpath-tui

Что такое wxpath?

wxpath — это декларативный веб-сканер, в котором обход выражается непосредственно в XPath. Вместо написания императивных циклов сканирования, wxpath позволяет описать, что отслеживать и что извлекать, в одном выражении. wxpath выполняет это выражение конкурентно, в стиле поиска в ширину, и передаёт результаты по мере их обнаружения.

Это выражение загружает страницу, извлекает ссылки и передаёт их конкурентно — без цикла сканирования:

root@kitploit:~
import wxpath

expr = "url('https://quotes.toscrape.com')//a/@href"

for link in wxpath.wxpath_async_blocking_iter(expr):
    print(link)

Благодаря оператору url(...) и синтаксису ///, движок wxpath может выполнять рекурсивный (или постраничный) веб-сканнинг и извлечение:

root@kitploit:~
import wxpath

path_expr = """
url('https://quotes.toscrape.com')
  ///url(//a/@href)
    //a/@href
"""

for item in wxpath.wxpath_async_blocking_iter(path_expr, max_depth=1):
    print(item)

Зачем wxpath?

Большинство веб-скраперов заставляют сначала писать управляющий код сканирования, а затем извлечение.

wxpath объединяет эти два шага в один:

  • Вы описываете обход декларативно
  • Извлечение выражается встроенно
  • Движок занимается планированием, конкурентностью и дедупликацией

Готовый вывод для RAG

Извлекайте чистые, структурированные иерархии JSON непосредственно из графа — подавайте в LLM сигнал, а не шум. Подробнее в разделе Интеграция с LangChain.

Детерминированность

wxpath детерминирован (читайте: не на основе LLM). Мы не можем гарантировать стабильность сети, но можем гарантировать предсказуемость обхода.

Документация (в разработке)

Документация доступна здесь.

Содержание

  • Пример: Граф знаний
  • Проектирование языка
  • Объяснение url(...) и ///url(...)
  • Общий поток
  • Асинхронное сканирование
  • Вежливое сканирование
  • Типы вывода
  • XPath 3.1 по умолчанию
  • Индикатор прогресса
  • CLI
  • TUI
  • Персистентность и кэширование
  • Настройки
  • Хуки (экспериментально)
  • Установка
  • Больше примеров
  • Сравнения
  • Продвинутая настройка движка и краулера
  • Философия проекта
  • Предупреждения
  • Коммерческая поддержка/консалтинг
  • Версионирование
  • Лицензия

Пример

root@kitploit:~
import wxpath
from wxpath.settings import CRAWLER_SETTINGS

# Пользовательские заголовки для вежливости; необходимы для некоторых сайтов (например, Wikipedia)
CRAWLER_SETTINGS.headers = {'User-Agent': 'my-app/0.4.0 (contact: [email protected])'}

# Сканирование, извлечение полей, построение графа знаний
path_expr = """
url('https://en.wikipedia.org/wiki/Expression_language')
  ///url(
        //main//a/@href[
            starts-with(., '/wiki/') and not(contains(., ':'))
        ]
    )
    /map{
        'title': (//span[contains(@class, "mw-page-title-main")]/text())[1] ! string(.),
        'url': string(base-uri(.)),
        'short_description': //div[contains(@class, 'shortdescription')]/text() ! string(.),
        'forward_links': //div[@id="mw-content-text"]//a/@href ! string(.)
    }
"""

for item in wxpath.wxpath_async_blocking_iter(path_expr, max_depth=1):
    print(item)

Примечание: Некоторые сайты (включая Wikipedia) могут блокировать запросы без правильных заголовков.
См. раздел Продвинутая настройка движка и краулера для установки пользовательского User-Agent.

Приведённое выше выражение делает следующее:

  1. Начинает с указанного URL, https://en.wikipedia.org/wiki/Expression_language.
  2. Фильтрует ссылки в разделе <main>, которые начинаются с /wiki/ и не содержат двоеточие (:).
  3. Для каждой найденной ссылки:
    • переходит по ссылке и извлекает заголовок, URL и краткое описание страницы;
    • повторяет шаг 2 до достижения максимальной глубины.
  4. Передаёт извлечённые данные по мере их обнаружения.

Объяснение url(...) и ///url(...)

  • url(...) — пользовательский оператор, который загружает содержимое указанного пользователем или созданного внутри URL и возвращает его как lxml.html.HtmlElement для дальнейшей обработки XPath.
  • ///url(...) указывает на глубокое сканирование. Он сообщает движку продолжать переход по ссылкам до указанного max_depth. В отличие от повторяющихся шагов url(), он позволяет одному выражению описывать более глубокое исследование графа. ВНИМАНИЕ: Используйте с осторожностью и ограничениями (через max_depth или предикаты XPath), чтобы избежать взрывного роста обхода.

Проектирование языка

Подробности проектирования языка см. в DESIGN.md. Вы увидите основные концепции и сможете спроектировать язык с нуля.

Общий поток

wxpath вычисляет выражение как список шагов обхода и извлечения (внутренне называемых Segment).

url(...) создаёт задачи сканирования либо статически (через фиксированный URL), либо динамически (через URL, полученный из выражения XPath). URL дедуплицируются глобально, по принципу best-effort, а не по глубине.

Сегменты XPath работают с загруженными документами (загруженными через непосредственно предшествующие операции url(...)).

///url(...) указывает на глубокое сканирование — оно выполняется примерно в ширину до max_depth.

Результаты передаются, как только они готовы.

Асинхронное сканирование

wxpath использует asyncio/aiohttp в первую очередь, предоставляя асинхронный API для сканирования и извлечения данных.

root@kitploit:~
import asyncio
from wxpath import wxpath_async

items = []

async def main():
    path_expr = "url('https://en.wikipedia.org/wiki/Expression_language')///url(//@href[starts-with(., '/wiki/')])//a/@href"
    async for item in wxpath_async(path_expr, max_depth=1):
        items.append(item)

asyncio.run(main())

Блокирующие конкурентные запросы

wxpath также предоставляет API asyncio-in-sync, позволяя сканировать несколько страниц конкурентно, сохраняя простоту синхронного кода. Это особенно полезно для сканирований в строго синхронных средах выполнения (т.е. не внутри цикла событий asyncio), где важна производительность.

root@kitploit:~
from wxpath import wxpath_async_blocking_iter

path_expr = "url('https://en.wikipedia.org/wiki/Expression_language')///url(//@href[starts-with(., '/wiki/')])//a/@href"
items = list(wxpath_async_blocking_iter(path_expr, max_depth=1))

Вежливое сканирование

wxpath по умолчанию соблюдает robots.txt через конструктор WXPathEngine(..., robotstxt=True).

Типы вывода

Python API wxpath возвращает структурированные объекты.

В зависимости от выражения, результаты могут включать:

  • объекты lxml.* и lxml.html.*
  • объекты elementpath.datatypes.* (для функций XPath 3.1)
  • WxStr (строковые значения с информацией о происхождении)
  • словари/карты
  • списки или другие нативные значения XPath

CLI преобразует эти объекты в простой JSON для отображения. Python API по умолчанию сохраняет структуру.

XPath 3.1 по умолчанию

wxpath использует библиотеку elementpath для поддержки XPath 3.1, что позволяет использовать продвинутые возможности, такие как карты, массивы и другое. Это позволяет писать более мощные запросы XPath.

root@kitploit:~
path_expr = """
    url('https://en.wikipedia.org/wiki/Expression_language')
    ///url(//div[@id='mw-content-text']//a/@href)
    /map{ 
        'title':(//span[contains(@class, "mw-page-title-main")]/text())[1], 
        'short_description':(//div[contains(@class, "shortdescription")]/text())[1],
        'url'://link[@rel='canonical']/@href[1]
    }
"""
# [...
# {'title': 'Computer language',
# 'short_description': 'Formal language for communicating with a computer',
# 'url': 'https://en.wikipedia.org/wiki/Computer_language'},
# {'title': 'Machine-readable medium and data',
# 'short_description': 'Medium capable of storing data in a format readable by a machine',
# 'url': 'https://en.wikipedia.org/wiki/Machine-readable_medium_and_data'},
# {'title': 'Domain knowledge',
# 'short_description': 'Specialist knowledge within a specific field',
# 'url': 'https://en.wikipedia.org/wiki/Domain_knowledge'},
# ...]

Индикатор прогресса

wxpath предоставляет индикатор прогресса (через tqdm) для отслеживания хода сканирования. Это особенно полезно для длительных сканирований.

Включите, установив engine.run(..., progress=True), или передайте progress=True в любую из функций wxpath_async*(...).

root@kitploit:~
items = wxpath.wxpath_async_blocking("...", progress=True)
> 100%|██████████████████████████████████████████████████████████▎| 469/471 [00:05<00:00, 72.00it/s, depth=2, yielded=457]

CLI

wxpath предоставляет интерфейс командной строки (CLI) для быстрого экспериментирования и выполнения выражений wxpath прямо из терминала.

Следующий пример демонстрирует, как сканировать Wikipedia, начиная со страницы "Expression language", извлекать ссылки на другие вики-страницы и получать определённые поля с каждой связанной страницы.

ПРИМЕЧАНИЕ: Из-за постоянно меняющегося содержимого веб-страниц вывод может со временем меняться.

root@kitploit:~
> wxpath --depth 1 \
    --header "User-Agent: my-app/0.1 (contact: [email protected])" \
    "url('https://en.wikipedia.org/wiki/Expression_language') \
    ///url(//div[@id='mw-content-text']//a/@href[starts-with(., '/wiki/') \
        and not(matches(@href, '^(?:/wiki/)?(?:Wikipedia|File|Template|Special|Template_talk|Help):'))]) \
    /map{ \
        'title':(//span[contains(@class, 'mw-page-title-main')]/text())[1], \
        'short_description':(//div[contains(@class, 'shortdescription')]/text())[1], \
        'url':string(base-uri(.)), \
        'backlink':wx:backlink(.), \
        'depth':wx:depth(.) \
        }"

{"title": "Computer language", "short_description": "Formal language for communicating with a computer", "url": "https://en.wikipedia.org/wiki/Computer_language", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
{"title": "Machine-readable medium and data", "short_description": "Medium capable of storing data in a format readable by a machine", "url": "https://en.wikipedia.org/wiki/Machine_readable", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
{"title": "Domain knowledge", "short_description": "Specialist knowledge within a specific field", "url": "https://en.wikipedia.org/wiki/Domain_knowledge", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
{"title": "Advanced Boolean Expression Language", "short_description": "Hardware description language and software", "url": "https://en.wikipedia.org/wiki/Advanced_Boolean_Expression_Language", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
{"title": "Data Analysis Expressions", "short_description": "Formula and data query language", "url": "https://en.wikipedia.org/wiki/Data_Analysis_Expressions", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
{"title": "Jakarta Expression Language", "short_description": "Computer programming language", "url": "https://en.wikipedia.org/wiki/Jakarta_Expression_Language", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
{"title": "Rights Expression Language", "short_description": [], "url": "https://en.wikipedia.org/wiki/Rights_Expression_Language", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
{"title": "Computer science", "short_description": "Study of computation", "url": "https://en.wikipedia.org/wiki/Computer_science", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}

Параметры командной строки:

root@kitploit:~
--depth                <depth>       Максимальная глубина сканирования
--verbose              [true|false]  Отображает поверхностную информацию CLI
--debug                [true|false]  Отображает подробный вывод и информацию времени выполнения
--concurrency          <concurrency> Количество одновременных запросов
--concurrency-per-host <concurrency> Количество одновременных запросов на хост
--header               "Key:Value"   Добавить пользовательский заголовок (например, 'Key:Value'). Можно использовать несколько раз.
--respect-robots       [true|false] (По умолчанию: True) Соблюдать robots.txt
--cache                [true|false] (По умолчанию: False) Сохранять результаты сканирования в локальную базу данных

TUI

wxpath предоставляет терминальный интерфейс (TUI) для интерактивного тестирования выражений и извлечения данных.

См. TUI Quickstart для подробностей.

Персистентность и кэширование

wxpath опционально сохраняет результаты сканирования в локальную базу данных. Это особенно полезно, когда вы сканируете большое количество URL и решаете приостановить сканирование, изменить выражения извлечения или перезапустить сканирование.

wxpath поддерживает два бэкенда: sqlite и redis. SQLite отлично подходит для небольших сканирований с одним рабочим процессом (т.е. engine.crawler.concurrency == 1). Redis хорошо подходит для крупномасштабных сканирований с несколькими рабочими процессами. Вы получите предупреждение, если min(engine.crawler.concurrency, engine.crawler.per_host) > 1 при использовании бэкенда sqlite.

Для использования необходимо установить соответствующую опциональную зависимость:

root@kitploit:~
pip install wxpath[cache-sqlite]
pip install wxpath[cache-redis]

После установки зависимости необходимо включить кэш:

root@kitploit:~
from wxpath.settings import SETTINGS

# Включить кэширование; по умолчанию sqlite
SETTINGS.http.client.cache.enabled = True

# Для бэкенда redis
SETTINGS.http.client.cache.enabled = True
SETTINGS.http.client.cache.backend = "redis"
SETTINGS.http.client.cache.redis.address = "redis://localhost:6379/0"

# Запуск wxpath как обычно
items = list(wxpath_async_blocking_iter('...', max_depth=1, engine=engine))

Настройки

Подробности настроек см. в settings.py.

Хуки (экспериментально)

wxpath поддерживает систему подключаемых хуков, позволяющую изменять поведение сканирования и извлечения. Вы можете регистрировать хуки для предварительной обработки URL, постобработки HTML, фильтрации извлечённых значений и т.д. Хуки выполняются в порядке их регистрации. Хуки могут влиять на производительность.

root@kitploit:~

from wxpath import hooks

@hooks.register
class OnlyEnglish:
    def post_parse(self, ctx, elem):
        lang = elem.xpath('string(/html/@lang)').lower()[:2]
        return elem if lang in ("en", "") else None

Асинхронное использование

ПРИМЕЧАНИЕ: Хуки могут быть синхронными или асинхронными, но все хуки в проекте должны следовать одному стилю. Смешивание синхронных и асинхронных хуков не поддерживается и может привести к неожиданному поведению.

root@kitploit:~

from wxpath import hooks

@hooks.register
class OnlyEnglish:
    async def post_parse(self, ctx, elem):
        lang = elem.xpath('string(/html/@lang)').lower()[:2]
        return elem if lang in ("en", "") else None

Предопределённые хуки

JSONLWriter (псевдоним NDJSONWriter) — встроенный хук, записывающий извлечённые данные в JSON-файл с разделителями строк. Это полезно для хранения результатов в структурированном формате, который можно легко обработать позже.

root@kitploit:~
from wxpath import hooks
hooks.register(hooks.JSONLWriter)

Установка

Требуется Python 3.10+.

root@kitploit:~
pip install wxpath

Для персистентности/кэширования wxpath поддерживает следующие бэкенды:

root@kitploit:~
pip install wxpath[cache-sqlite]
pip install wxpath[cache-redis]

Больше примеров

См. EXAMPLES.md для дополнительных примеров использования.

Сравнения

См. COMPARISONS.md для сравнения с другими инструментами веб-скрапинга.

Продвинутая настройка движка и краулера

Вы можете изменить поведение движка и краулера следующим образом:

root@kitploit:~
from wxpath import wxpath_async_blocking_iter
from wxpath.core.runtime import WXPathEngine
from wxpath.http.client.crawler import Crawler

crawler = Crawler(
    concurrency=8,
    per_host=2,
    timeout=10,
    respect_robots=False,
    headers={
        "User-Agent": "my-app/0.1.0 (contact: [email protected])", # Такие сайты, как Wikipedia, оценят это
    },
)

# Если `crawler` не указан, будет создан Crawler по умолчанию
# с переданными значениями concurrency, per_host, respect_robots или значениями по умолчанию.
engine = WXPathEngine(
    # concurrency: int = 16, 
    # per_host: int = 8,
    # respect_robots: bool = True,
    # allowed_response_codes: set[int] = {200},
    # allow_redirects: bool = True,
    crawler=crawler,
)

path_expr = "url('https://en.wikipedia.org/wiki/Expression_language')//url(//main//a/@href)"

items = list(wxpath_async_blocking_iter(path_expr, max_depth=1, engine=engine))

Параметры Runtime API (wxpath_async*)

  • max_depth: int = 1
  • progress: bool = False
  • engine: WXPathEngine | None = None
  • yield_errors: bool = False

Настройки

Вы также можете использовать settings.py для включения кэширования, троттлинга, конкурентности и т.д.

Философия проекта

Принципы

  • Сделать возможным декларативное сканирование и парсинг без шаблонного кода
  • Оставаться лёгким и компонуемым
  • Асинхронная поддержка для высокопроизводительного сканирования

Цели

  • URL дедуплицируются по принципу best-effort в рамках одного сканирования.
  • Сканирование завершается, когда фронтир исчерпан или достигнут max_depth.
  • Запросы выполняются конкурентно.
  • Результаты передаются по мере готовности.

Ограничения (на данный момент)

Следующие функции пока не поддерживаются:

  • Автоматическая смена прокси
  • Рендеринг на основе браузера (выполнение JavaScript)
  • Строгий порядок результатов

ВНИМАНИЕ!!!

Этот проект находится на ранней стадии разработки. Основные концепции стабильны, но API и функции могут измениться. Пожалуйста, сообщайте об ошибках — особенно о взаимоблокировках сканирования или неожиданном поведении — и о любых функциях, которые вы хотели бы видеть (нет гарантии, что они будут реализованы).

  • Будьте уважительны при сканировании веб-сайтов. По умолчанию включён троттлер, вдохновлённый Scrapy.
  • Глубокое сканирование (///) требует дисциплины пользователя, чтобы избежать неограниченного расширения (взрывного роста обхода).
  • Взаимоблокировки и зависания возможны в определённых ситуациях (например, все задачи ожидают заблокированные запросы). Пожалуйста, сообщайте о проблемах, если вы столкнулись с таким поведением.
  • Рассмотрите возможность использования тайм-аутов, max_depth, а также предикатов и фильтров XPath для ограничения области сканирования.

Коммерческая поддержка / консалтинг

Если вам нужна помощь в создании или эксплуатации сканеров/потоков данных с wxpath (извлечение, планирование, мониторинг, исправление поломок) или другие потребности веб-скрапинга, свяжитесь со мной по адресу: [email protected].

Пожертвования

Если вам нравится wxpath и вы хотите поддержать его развитие, рассмотрите возможность пожертвования.

Версионирование

wxpath следует semver: <MAJOR>.<MINOR>.<PATCH>.

Однако до версии 1.0.0 используется 0.<MAJOR>.<MINOR|PATCH>.

Лицензия

AGPL-3.0

Скачать инструмент