2017-01-08 9 views
0

Я не понимаю, почему этот кодR: xml2 извлекает больше узлов, чем ожидалось

library(rvest) 
u <- "http://alistapart.com/article/daemonskin" 
h <- read_html(u) 
html_nodes(h, "div.main-content[itemprop='articleBody'] a") %>% 
    html_attr("href") 

матчи много URL-адресов, которые выходят за рамки целевого <div> элемента.

Если вы посмотрите на HTML источнике target page:

  • Существует только один <div>, который соответствует моему запросу. Она начинается в строке 177.
  • The <div> останавливается на линии 396.
  • Тем не менее многие из URL-адресов, возвращенных html_nodes в коде выше извлекается из узлов за пределами этой линии, за пределами этого <div>.

Примечание: Вы могли бы заметить, что в строке 242 HTML, есть неисправный элемент </div. Однако исправление этого вопроса, похоже, не устраняет проблему.

Я думаю, что проблема связана с тем, как xml2 (т. Е. libxml2) анализирует код.

Любые другие идеи?

ответ

1

Ну, проблема Основная проблема - плохо разработанный, несовместимый HTML на сайте, который гордится тем, что на самом деле умнее всех в этом отношении.

Когда вы делаете:

library(rvest) 
library(purrr) 

URL <- "http://alistapart.com/article/daemonskin" 

read_html(URL) %>% 
    html_nodes("div.main-content[itemprop='articleBody'] a") %>% 
    html_attr("href") %>% 
    str() 
## chr [1:74] "#comments" ... 

лежащие в основе libxml2 библиотеки «подправить» незначительные HTML ошибки (XML) и имеет свой собственный способ делать вещи. Такие способы вызывают большее количество элементов под этим конкретным <div>, на которые вы нацеливаетесь из-за того, как синтаксический анализатор «исправил» HTML.

Вы можете увидеть разницу с результатами от реального браузера, который мы можем симулировать с селеном:

ПРИМЕЧАНИЕ: Я начал phantomjs в режиме WebDriver вне R

library(seleniumPipes) 

rd <- remoteDr(browserName = "phantomjs", port = 8910) 
rd %>% go(URL) 

Когда вы сделаете это , это phantomjs (webkit, на самом деле), применяя собственные методы проверки парсера HTML на основе браузера к HTML, который он получает (а также добавляет или вычитает узлы на основе любых триггеров javascript при загрузке страницы).

При использовании эквивалент document.querySelectorAll() для извлечения узлов вы получаете 34 (который также является то, что я попал в Chrome в консоли инструментов разработчика):

rd %>% 
    findElements("css", "div.main-content[itemprop='articleBody'] a") %>% 
    map_chr(getElementAttribute, "href") %>% 
    str() 
## chr [1:34] "http://alistapart.com/article/daemonskin#comments" ... 

Обратите внимание, что если вы решили сделать то, что я обычно делают и используют getPageSource() для выполнения всех операций выбора/извлечения через функции /xml2, вы получите другой результат, так как он извлекает текущую HTML-страницу из виртуального браузера и передает ее read_html(), которая имеет libxml2, применяя некоторые дополнительные исправления для чего webkit теоретически уже очищен:

rd %>% 
    go(URL) %>% 
    getPageSource() %>% 
    html_nodes("div.main-content[itemprop='articleBody'] a") %>% 
    html_attr("href") %>% 
    str() 
## chr [1:32] "#comments" ... 
+0

Благодарим вас за доказательство 'phantomjs', что проблема связана с HTML и как' libxm2' исправил его. Однако это странная проблема, и я не нашел, как на самом деле исправлять код (что добавить/удалить из него), чтобы решить проблему. Вы нашли тег, ответственный за проблему? –

+0

Кроме того, спасибо за редактирование вопроса, чтобы улучшить маркировку. –

+0

selenium или phantom rly не так уж плохо, чтобы попасть в систему. я попытаюсь выработать некоторое время, чтобы сравнить структурные изменения документа. – hrbrmstr

 Смежные вопросы

  • Нет связанных вопросов^_^