Кукловод: избавьтесь от квадратных скобок в селекторе.

Мне нужно выбрать элементы с идентификаторами, содержащими квадратные скобки.

т.е.

#element[0]

Однако я продолжаю получать:

Error: failed to find element matching selector "element[0]"

Я экранировал элемент в селекторе с помощью \, но это не работает.

page.select("#fruit\[0\]", "apples")

Двойные символы обратной косой черты тоже не работают. то есть:

page.select("#fruit\\[0\\]", "apples")

ОБНОВЛЕНИЕ: элемент, который я пытаюсь выбрать:

<select id="fruit[0]">
  <option>Please make a selection</option>
  <option>apples</option>
</select>

ПРИМЕЧАНИЕ. Я получаю ту же ошибку, даже когда пытаюсь использовать метод page.waitFor с указанным выше запросом.

0
0
1 230
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Экранирование с использованием закодированных данных

Если вы даже попытаетесь выполнить document.querySelector('#fruit[0]') в своем браузере, вы получите ту же ошибку. Экранирование не работает, потому что к тому времени, когда кукловод его прочитает, он уже проанализирован и не имеет такого же экранированного значения. Несколько способов убежать от них.

Скажем, у нас есть такой элемент,

<a href="/" id="sample[112]">Bar</a>

Теперь, если вы хотите использовать vanila JS, вы можете попробовать следующее:

enter image description here

Что гласит следующее:

< document.querySelector(CSS.escape('#sample[112]'))
> null

< document.querySelector('#sample[112]')
> Uncaught DOMException: Failed to execute 'querySelector' on 'Document': '#sample[112]' is not a valid selector.

< document.querySelector('#sample\5b 112\5d')
> ncaught DOMException: Failed to execute 'querySelector' on 'Document': '#sampleb 112d' is not a valid selector.

< document.querySelector('#sample\\5b 112\\5d')
> <a href="/" id="sample[112]">Bar</a>

Как вы можете видеть выше, левая скобка - это 5b, а правая скобка - это 5d, и нам даже пришлось избежать этого и нужно было оставить место, чтобы браузер мог его проанализировать.

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

Скрипты реального дела

Посмотрим правде в глаза, ваш целевой веб-сайт не имеет ценности для опций. Лучшим способом будет выделение по тексту, беззастенчиво копируя из этот ответ.

Кроме того, я мог дважды избежать этого и получить данные, не кодируя их. В конце концов, nodeJS отличается от консоли браузера, и все будет действовать по-другому в сценарии.

Источник, используемый для HTML,

<select id="sample[1]"><option>mango</option><option>apple</option></select>

И код кукольника, используемый для тестирования,

const puppeteer = require("puppeteer");

function setSelectByText(selector, text) {
  // Loop through sequentially//
  const ele = document.querySelector(selector);
  console.log(ele);

  for (let ii = 0; ii < ele.length; ii++) {
    if (ele.options[ii].text == text) {
      // Found!
      ele.options[ii].selected = true;
      return true;
    }
  }
  return false;
}

puppeteer.launch().then(async browser => {
  console.log("Opening browser");
  const page = await browser.newPage();

  console.log("Going to site");
  await page.goto("http://0.0.0.0:8080"); // temporary website created for testing

  await page.evaluate(setSelectByText, "#sample\\[1\\]", "apple"); // we can use this over and over, without creating a separate function, just passing them as arguments

  await page.screenshot({ path: "test.png" });

  await browser.close();
});

enter image description here

Я только что пробовал это. Не повезло :(. Я получаю ту же ошибку: (узел: 4995) UnhandledPromiseRejectionWarning: Ошибка: Ошибка оценки: DOMException: Не удалось выполнить querySelector в документе Document: '#fruit [0]' не является допустимым селектором. в puppeteer_evaluation_script: 1: 33

kashiB 10.09.2018 08:30

А, подождите, я вспомнил о проблеме, позвольте мне скоро вернуться с твердым ответом.

Md. Abu Taher 10.09.2018 08:31

@kashiB Теперь я добавил еще ответ. :) Мир.

Md. Abu Taher 10.09.2018 08:43

Я ценю усилия Md :) К сожалению, ни одно из предложений не сработало. Error: failed to find element matching selector "#fruits\5b 0\5d Я собираюсь пока придерживаться Selenium, так как у меня там работает мой скрипт. Я смотрел на Puppeteer, потому что облачные функции Google теперь поддерживают безголовый Chrome с Puppeteer в среде выполнения Node. Думаю, это убедило меня пока просто придерживаться экземпляра вычислительной машины Java.

kashiB 10.09.2018 08:51

У меня была такая же проблема, поэтому я предложил это. Я дал решение из реального приложения. :) Может чего-то маленького не хватает.

Md. Abu Taher 10.09.2018 08:53

@kashiB в последний раз попытался помочь, проверьте и попробуйте еще раз. Что еще можно сказать.

Md. Abu Taher 10.09.2018 09:22

Раздел о обратных кавычках вводит в заблуждение: "#fruit[0]" так же эффективен, как и версия с обратными кавычками, и если вас беспокоят странные и необычные селекторы, последний сломается, когда вы попытаетесь сопоставить input[value="${foo}"]. Что касается сопоставления по тексту, учитывая, что мы говорим о Puppeteer, было бы более эффективно и надежно использовать использовать $x с предложением contains, чем использовать собственную функцию.

Aankhen 10.09.2018 12:09

@Aankhen, ты на месте. Можем ли мы использовать xpath для выбора параметров по тексту? :) Если да, напишите ответ, чтобы я мог проголосовать за него: D

Md. Abu Taher 10.09.2018 19:48

Да, вы можете (см. Ссылку в моем предыдущем комментарии), но я не думаю, что проблема здесь, хех.

Aankhen 10.09.2018 19:59

@Aankhen Спасибо. $x работает для waitFor, но я все еще застрял, пытаясь установленный выбрать значение элемента.

kashiB 11.09.2018 17:42

Ах, теперь я понимаю. Позвольте мне это записать.

Aankhen 11.09.2018 18:18

Вау, ты все еще застрял? Ах, кажется, мне нужно попробовать это на GCP.

Md. Abu Taher 11.09.2018 18:19

См. Ответ Гранта Миллера.

Aankhen 11.09.2018 18:27

Возможно, вы неправильно указываете идентификатор.

Если вы программно генерируете идентификаторы при создании элементов HTML (например, fruit[0], fruit[1]), то сохраняется ссылка на ценность, а не.

Пример: у меня есть массив fruit = [apple, banana] и я создаю элемент ... <button id=fruit[0]>Click me</button> Если я хочу нажать эту кнопку, мне понадобится page.select('#apple')вместо тогоpage.select('#fruit[0]')

Ничего. Я вижу, что в примере вы используете кавычки, поэтому строка должна сохраняться точно так, как вы ее устанавливаете.

Taylor Krusen 10.09.2018 08:36

Возможно. Но почему это тоже не работает: await page.waitFor('#answerlist[0]')

kashiB 10.09.2018 08:36

Учтите, что это зависит от того, как вы создаете элемент. Если я скажу document.body.innerHTML = "<button id=fruit[0]>Click me</button>", идентификатором будет буквальная строка fruit[0], а не первый элемент массива fruit, и правильным селектором будет #fruit\[0\].

Aankhen 10.09.2018 12:02
Ответ принят как подходящий

Используйте [id="fruit[0]"]:

Вы можете использовать CSS селектор атрибутов со ссылкой на атрибут id элемента:

await page.waitFor( '[id="fruit[0]"]' );

await page.select( '[id="fruit[0]"]', 'apples' );

Другие вопросы по теме