Методы для навигации

Find

Команда find используется для навигации по DOM структуре загруженного документа. Чтобы находить определенные элементы, вы можете использовать CSS селекторы.

Полезная информация о команде find, которую необходимо знать:

  1. Каждый раз выполняя команду find и заходя в найденный блок, диггер создает новый блоковый контекст
  2. Если по заданному CSS селектору диггер находит более чем один элемент, диггер проходит последовательно во все найденные блоки и выполняет команды в параметре do для каждого из них
  3. Если диггер нашел несколько элементов, можно ограничить выбор срезом с помощью параметра slice
  4. В CSS селекторе можно использовать переменные, аргументы и даже регулярные выражения
  5. Вы можете объединить найденные элементы в один элемент, используя параметр merge

Ниже приведен ряд примеров CCS селекторов:

          # ПОИСК ПО ТЕГУ
- find:
    path: body > div
    do:

# ПОИСК ПО КЛАССУ
- find:
    path: body > .someclass
    do:

# ПОИСК ПО ТЕГУ С КЛАССОМ
- find:
    path: body > div.someclass
    do:

# ПОИСК ПО ID, ОБРАТИТЕ ВНИМАНИЕ СЕЛЕКТОР ДОЛЖЕН БЫТЬ ЗАКЛЮЧЕН В КАВЫЧКИ
- find:
    path: 'body > #someid'
    do:

# ПОИСК ПО ТЕГУ С ID, ОБРАТИТЕ ВНИМАНИЕ СЕЛЕКТОР ДОЛЖЕН БЫТЬ ЗАКЛЮЧЕН В КАВЫЧКИ
- find:
    path: 'body > div#someid'
    do:

# ПОИСК ПО НЕСКОЛЬКИМ СЕЛЕКТОРАМ, ВСЕ НАЙДЕННЫЕ ЭЛЕМЕНТЫ БУДУТ ВКЛЮЧЕНЫ В ВЫБОРКУ
- find:
    path: 'body > #someid, body > .someclass, body > div'
    do:

# :HAS СЕЛЕКТОР, НАЙДЕТ ВСЕ .someclass В КОТОРЫХ ЕСТЬ td
- find:
    path: body > .someclass:has(td)
    do:

# :CONTAINS СЕЛЕКТОР, НАЙДЕТ ВСЕ .someclass В КОТОРЫХ ЕСТЬ td В КОТОРЫХ ЕСТЬ ТЕКСТ sometext.
- find:
    path: body > .someclass:has(td:contains('sometext'))
    do:

# :MATCHES СЕЛЕКТОР, НАЙДЕТ ВСЕ .someclass В КОТОРЫХ ЕСТЬ td ДЛЯ КОТОРЫХ ВЕРНО РЕГУЛЯРНОЕ ВЫРАЖЕНИЕ
- find:
    path: body > .someclass:has(td:matches(^\s*sometext\s*$))
    do:

# * СЕЛЕКТОР, НАЙДЕТ ВСЕ .someclass ID КОТОРЫХ СОДЕРЖИТ 123
- find:
    path: body > .someclass[id*="123"]
    do:

# ПОИСК ПО КЛАССУ, И ВЫБОРКА ВСЕХ ЭЛЕМЕНТОВ КРОМЕ ПЕРВОГО, ДОПУСТИМА ЗАПИСЬ slice: 1, slice: -1, slice: 0:1
- find:
    path: body > .someclass
    slice: 1:-1
    do:

# ПОИСК ПО КЛАССУ, И ОБЪЕДИНЕНИЕ ВСЕХ ЭЛЕМЕНТОВ В 1 ЭЛЕМЕНТ С ТЭГОМ p
- find:
    path: body > .someclass
    merge: p
    do:

# ПОИСК ПО ВСЕМУ ДОКУМЕНТУ ИЗ ЛЮБОГО БЛОКА
- find: 
    path: body > div
    do:
    - find:
        # ЯВНО УКАЖЕМ ЧТО ОСУЩЕСТВЛЯЕМ ПОИСК ПО ВСЕМУ ДОКУМЕНТУ
        in: doc
        path: body > ul > li
        do:
          

Командой find поддерживаются следующие параметры:

Параметр Описание
path CSS селектор, по которому диггер будет искать элементы. Примите во внимание, что поиск осуществляется в текущем блоке, если команда вызвана из блокового контекста, поэтому вы должны использовать относительный путь. Если же команда вызвана из страничного контекста, поиск осуществяется по всему документу.
form CSS селектор, по которому диггер будет искать формы. Примите во внимание, что поиск осуществляется в текущем блоке, если команда вызвана из блокового контекста, поэтому вы должны использовать относительный путь. Если же команда вызвана из страничного контекста, поиск осуществяется по всему документу. Если поиск был удачный диггер переходит в контекст формы.
in Специальный флаг, указывающий где производить поиск. В настоящий момент поддерживает только одно возможное значение doc, использовав который можно заставить диггер в блоковом контексте искать не в текущем блоке, а во всем документе.
merge Объединяет контент всех найденных элементов в один блок и переходит в него, для выполнения дальнейших команд над этим блоком. Если в параметре передана не пустая строка, то значение будет считаться тегом и каждый найденный элемент будет вписан в этот тег.

Теперь давайте рассмотрим более детальные примеры использования команды find. В качестве примера будем использовать следующий фрагмент HTML документа:

          <ul>
  <li>Some text</li>
  <li>Some other text</li>
  <li>Some other other text</li>
</ul>
          

Посмотрите как диггер будет проходить по найденным элементам и что будет в блоке на каждом этапе итераций:

              - find:
    path: li
    do:
    - parse
              
              - find:
    path: li
    do:
    # СЕЙЧАС МЫ НАХОДИМСЯ В ПЕРВОМ `<li>` ЭЛЕМЕНТЕ, ГДЕ <li>Some text</li>
    # СОДЕРЖИМОЕ РЕГИСТРА ""
    - parse
    # СОДЕРЖИМОЕ РЕГИСТРА "Some text"
              
            - find:
    path: li
    do:
    # СЕЙЧАС МЫ НАХОДИМСЯ ВО ВТОРОМ `<li>` ЭЛЕМЕНТЕ <li>Some other text</li>
    # СОДЕРЖИМОЕ РЕГИСТРА ""
    - parse
    # СОДЕРЖИМОЕ РЕГИСТРА "Some other text"
            
            - find:
    path: li
    do:
    # СЕЙЧАС МЫ НАХОДИМСЯ В ТРЕТЬЕМ `<li>` ЭЛЕМЕНТЕ <li>Some other other text</li>
    # СОДЕРЖИМОЕ РЕГИСТРА ""
    - parse
    # СОДЕРЖИМОЕ РЕГИСТРА "Some other other text"
            

Еще варианты использования:

              # ПРОСТОЙ ПОИСК `ul` ЭЛЕМЕНТА
- find:
    path: ul
    do:
    # СЕЙЧАС МЫ НАХОДИМСЯ В `ul`
    - parse
    # СОДЕРЖИМОЕ РЕГИСТРА: "Some textSome other textSome other other text"
              
              # ПРОСТОЙ ПОИСК `ul` ЭЛЕМЕНТА
- find:
    path: ul > li
    slice: 1
    do:
    # СЕЙЧАС МЫ НАХОДИМСЯ В <li>Some other text</li>
    - parse
    # СОДЕРЖИМОЕ РЕГИСТРА: "Some other text"
              
              # ПОИСК `ul` ЭЛЕМЕНТА
- find:
    path: ul > li
    merge: p
    do:
    # ТЕПЕРЬ БЛОК СОДЕРЖИТ:
    #   <p>Some text</p>
    #   <p>Some other text</p>
    #   <p>Some other other text</p>
    - parse
    # СОДЕРЖИМОЕ РЕГИСТРА: "Some textSome other textSome other other text"

# ПОИСК `ul` ЭЛЕМЕНТА
- find:
    path: ul > li
    merge: ""
    do:
    # ТЕПЕРЬ БЛОК СОДЕРЖИТ:
    #   Some textSome other textSome other other text
    - parse
    # СОДЕРЖИМОЕ РЕГИСТРА: "Some textSome other textSome other other text"
                

Как уже упоминалось ранее, если вы находитесь в блоковом контексте, то и поиск вы можете делать только в текущем блоке, и находить только элементы из текущего блока. Поэтому ваш CSS селектор должен быть построен относительно вашего текущего местоположения (блока). Давайте подробно рассмотрим это на следующем примере:

          <body>
<div>
  <p>Some text</p>
  <p>Some other text </p>
  <p>Some other other text</p>
</div>
<div>
  <a>Some text</a>
  <a>Some other other text</a>
</div>
</body>
          

Использовав CSS путь body > div, мы получим два блока:

          - find:
    path: body > div
    # do-1
    do:
    # ЭТОТ СЕЛЕКТОР НАЙДЕТ ДВА БЛОКА `div`
    # первый блок:
    # <div>
    #    <p>Some text</p>
    #    <p>Some other text </p>
    #    <p>Some other other text</p>
    # </div>

    # и второй блок:
    # <div>
    #    <a>Some text</a>
    #    <a>Some other other text</a>
    # </div>
    
    # ВЫБЕРЕМ `а` ВНУТРИ КАЖДОГО `div`
    - find:
        path: a
        # do-2
        do:
          

Логика данного сценария сводится к следующему:

  1. Диггер найдет все блоки div в первом селекторе, и для каждого начнет выполнять команды указанные в do-1
  2. Диггер заходит в первый блок div и пытается найти блоки по селектору a
  3. В первом блоке нет найденных элементов, поэтому диггер выходит из первого div
  4. Диггер заходит во второй блок div и пытается найти блоки по селектору a
  5. Во втором блоке есть два элемента a, поэтому диггер начинатет проходить по обеим и выполнять команды, заданные в do-2

Если, находясь в блоковом контексте, вам нужно найти элементы за пределами текущего блока, вы можете использовать опцию in со значением doc для поиска по всему документу:

          - find:
    path: body > div > ul > li
    do:
    - find:
        # ЯВНО УКАЖЕМ, ЧТО ОСУЩЕСТВЛЯЕМ ПОИСК ВО ВСЕМ ДОКУМЕНТЕ
        in: doc
        path: body > div > a
        do:
          

В следующей главе мы детально рассмотрим применение параметра form команды find.