Я прочитал этот вопрос и этот вопрос, и, возможно, больше вопросов, и хочу сделать именно то, что они там делают, но я просто получаю пустые результаты, когда пытаюсь.
Я хочу извлечь ссылку на профиль для всех подписчиков здесь https://www.facebook.com/zuck/followers
Очень грубый Xpath, указывающий на имя подписчика, которое является кликабельной ссылкой: //*[@id = "mount_0_0_MW"]/div/div[1]/div/div[3]/div/div/div/div[1]/div[1]/div/div/div[4]/div/div/div/div/div/div/div/div/div[3]/div/div[2]/div[1]/a
Тег a, на который я указываю, обычно выглядит примерно так:
<a class = "x1i10hfl xjbqb8w x6umtig x1b1mbwd xaqea5y xav7gou x9f619 x1ypdohk xt0psk2 xe8uvvx xdj266r x11i5rnm xat24cr x1mh8g0r xexx8yu x4uap5 x18d9i69 xkhd6sd x16tdsg8 x1hl2dhg xggy1nq x1a2a7pz x1heor9g xt0b8zv" href="https://www.facebook.com/profile.php?id=100072622654958" role = "link" tabindex = "0">
Чтобы извлечь значение href, я, согласно связанному вопросу, добавляю /@href в конец xpath выше, но когда я оцениваю это выражение, используя $x в консоли браузера (в Safari), я получаю пустой результат:
Как мне переписать свой xpath, чтобы получить массив со значениями в атрибуте href при его оценке?
@MartinHonnen Я не уверен, что следую за тобой. Что должно делать ваше выражение?
«Обратите внимание, что используемый XPath немного отличается от вашего, поскольку вы ничего не выбрали для меня» - да, это моя проблема и причина, по которой я задал этот вопрос. Когда я выполняю ваше выражение в консоли Safari, я получаю [] (0) = $10-, что тоже немного пусто. Вы получаете другой результат, чем я? Спасибо.
Я понял из вашего описания, что для вашего, например. $x('//*[@id = "mount_0_0_MW"]/div/div[1]/div/div[3]/div/div/div/div[1]/div[1]/div/div/div[4]/div/div/div/div/div/div/div/div/div[3]/div/div[2]/div[1]/a') выбрал нужные a элементы в вашем браузере, но каким-то образом попытка использовать путь $x('//*[@id = "mount_0_0_MW"]/div/div[1]/div/div[3]/div/div/div/div[1]/div[1]/div/div/div[4]/div/div/div/div/div/div/div/div/div[3]/div/div[2]/div[1]/a'/@href) каким-то образом с API/движком XPath вашего браузера не удалась.
Поэтому я предложил альтернативу для получения значения атрибута/свойства href, а именно $x('//*[@id = "mount_0_0_MW"]/div/div[1]/div/div[3]/div/div/div/div[1]/div[1]/div/div/div[4]/div/div/div/div/div/div/div/div/div[3]/div/div[2]/div[1]/a').map(link => link.href). Только для тестирования в Chrome в Windows мне нужно было использовать другое выражение пути, а именно //*[@id = "mount_0_0_OV"]/div/div[1]/div/div[3]/div/div/div/div[1]/div[1]/div/div/div[4]/div/div/div/div/div/div/div/div/div[3]/div[2]/div[2]/div[1]/a.
@MartinHonnen Xpath, оканчивающийся на @href, терпит неудачу в том отношении, что он не возвращает атрибут @href, а просто возвращает пустую строку (или массив пустых строк).
@MartinHonnen Ваш пример, оканчивающийся на .map(link => link.href), сработал. Спасибо. Как вы думаете, вы можете объяснить, почему / как это работает? Если вы опубликуете это как ответ, я приму это решение.

Попробуйте XPath следующим образом:
//a[starts-with(@href, "https://www.facebook.com/profile.php?")]/@href
В инструментах разработчика Chrome:
$x('//a[starts-with(@href, "https://www.facebook.com/profile.php?")]/@href')
Результат:
Array(24) [
href = "https://www.facebook.com/profile.php?id=100025227933647",
href = "https://www.facebook.com/profile.php?id=100025227933647",
href = "https://www.facebook.com/profile.php?id=100004202773657",
href = "https://www.facebook.com/profile.php?id=100004202773657",
href = "https://www.facebook.com/profile.php?id=100089136296666",
href = "https://www.facebook.com/profile.php?id=100089136296666",
href = "https://www.facebook.com/profile.php?id=100088772316924",
href = "https://www.facebook.com/profile.php?id=100088772316924",
href = "https://www.facebook.com/profile.php?id=100090228025189",
href = "https://www.facebook.com/profile.php?id=100090228025189",
… ]
... или, может быть, если вы хотите начать с ограничения поиска в определенной части страницы, как в приведенном выше примере XPath:
//*[@id = "mount_0_0_MW"]//a[starts-with(@href, "https://www.facebook.com/profile.php?")]/@href
Это поиск a элементов, ссылки на которые ведут на страницы профиля Facebook.
Я видел много вопросов на этом сайте, когда у людей возникают проблемы с XPath, предложенным их браузером, и их выражение выглядит примерно так:
/div[2]/div[2]/div[1]/div[3]/div[1]/a
Выражения XPath, подобные этим, легко генерируются браузером, так как они просто восходят от выбранного элемента вверх по иерархии элементов, считая предшествующих братьев и сестер на каждом уровне. Но обычно они не очень надежны, потому что они зависят от HTML-страницы, имеющей фиксированную структуру, которая не меняется. Если бы страница добавила дополнительный элемент div в какой-то ключевой части страницы, то XPath мог бы легко в конечном итоге указать куда-то не туда, куда он указывал раньше.
По моему мнению, людям часто лучше самим написать XPath, который выражает то, что они на самом деле ищут. В вашем случае вы на самом деле не ищете элементы a, которые появляются на определенном уровне в иерархии div; вы на самом деле ищете ссылки на профили. XPath, ориентированный на семантику вашего поиска, вероятно, будет более надежным и устойчивым перед лицом изменений.
Я согласен с вашим советом по написанию собственных xpaths, и я обычно делаю это, когда делаю что-то более постоянное. В этом случае я просто использовал xpath браузера, потому что мне нужно было что-то для вопроса. В любом случае, проблема остается, даже когда я пробую ваши xpaths, я не получаю атрибут href. Вы пробовали ваши предложения?
Я выполнил свое первое предложение в инструментах разработчика Chrome, используя функцию $x, и получил список элементов a.
Мне было непонятно, какое клиентское приложение вы пишете; может быть, Selenium, может быть, пользовательский скрипт браузера (JS)? Поэтому я просто написал XPath для извлечения элементов a. Может быть, вам нужно показать остальную часть вашего кода?
Я отредактировал свой ответ, чтобы показать результаты, которые я получил
Когда я выполняю ваше предложение, вот результат: imgur.com/a/tZ9HO7y
Я пишу AppleScript для управления Safari, используя do javascript-метод Safari.
Это странно, когда я пытаюсь $x('//a[starts-with(@href, "https://www.facebook.com/profile.php?")]/@href') иногда получается результат, а иногда нет. Firefox работал imgur.com/a/vjOmPnw, но Chrome и Safari возвращают пустые результаты.
Основываясь на вашем описании (и без доступа к Mac/Safari для тестирования), похоже, что оценка XPath для узла атрибута каким-то образом терпит неудачу, в качестве альтернативы я думаю, что вы можете полагаться на XPath только для выбора элементов @href. , затем используйте методы массива JavaScript, такие как a (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) и обычные свойства DOM браузера, такие как map; это означало бы, что вы используете, например.
$x('//*[@id = "mount_0_0_MW"]/div/div[1]/div/div[3]/div/div/div/div[1]/div[1]/div/div/div[4]/div/div/div/div/div/div/div/div/div[3]/div/div[2]/div[1]/a').map(link => link.href)
где вызов .href возвращает массив узлов элементов $x(..), а последующий вызов a отображает этот массив узлов элементов map в массив строковых значений на основе свойства a элементов href.
Вы никогда не сможете быть счастливы ... Я пытаюсь использовать это с document.evaluate, но, как бы я ни использовал суффикс, который вы предлагаете, .map(link => link.href) я не могу заставить его работать. «Корневой» xpath работает нормально, но как только я добавляю .map(link => link.href), я получаю различные сообщения об ошибках, в основном «TypeError Map не является функцией». Есть идеи, как использовать .map(link => link.href) с document.evaluate? Спасибо.
Метод map работает с массивами или объектами, подобными массивам; document.evaluate ничего подобного не возвращает.
Результатом
$xявляется массив, поэтому вы также можете использовать функции массива, такие какmap, например.$x('//*[@id = "mount_0_0_OV"]/div/div[1]/div/div[3]/div/div/div/div[1]/div[1]/div/div/div[4]/div/div/div/div/div/div/div/div/div[3]/div[2]/div[2]/div[1]/a').map(link => link.href)для дальнейшей обработки. (Обратите внимание, что используемый XPath немного отличается от вашего, поскольку вы ничего не выбрали для меня, поэтому я позволил браузеру предложить мне тот, который используется в моем примере).