#r #web #screen-scraping #web-crawler
#r #веб #очистка экрана #веб-сканер
Вопрос:
Я пытаюсь написать код, который будет переходить на каждую страницу и брать оттуда информацию. URL <-http://www.wikiart.org/en/claude-monet/mode/all-paintings-by-alphabet
У меня есть код для вывода всех hrefs. Но это не работает.
library(XML)
library(RCurl)
library(stringr)
tagrecode <- readHTMLTable ("http://www.wikiart.org/en/claude-monet/mode/all- paintings-by-alphabet")
tabla <- as.data.frame(tagrecode)
str(tabla)
names (tabla) <- c("name", "desc", "cat", "updated")
str(tabla)
res <- htmlParse ("http://www.wikiart.org/en/claude-monet/mode/all-paintings-by- alphabet")
enlaces <- getNodeSet (res, "//p[@class='pb5']/a/@href")
enlaces <- unlist(lapply(enlaces, as.character))
tabla$enlace <- paste("http://www.wikiart.org/en/claude-monet/mode/all-paintings-by- alphabet")
str(tabla)
lisurl <- tabla$enlace
fu1 <- function(url){
print(url)
pas1 <- htmlParse(url, useInternalNodes=T)
pas2 <- xpathSApply(pas1, "//p[@class='pb5']/a/@href")
}
urldef <- lapply(lisurl,fu1)
После того, как у меня будет список URL-адресов всех изображений на этой странице, я хочу перейти на вторую-третью- …-23 страницы, чтобы собрать URL-адреса всех изображений.
Следующий шаг — удалить информацию о каждом изображении. У меня есть рабочий код для одного, и мне нужно собрать его в один общий код.
library(XML)
url = "http://www.wikiart.org/en/claude-monet/camille-and-jean-monet-in-the-garden-at-argenteuil"
doc = htmlTreeParse(url, useInternalNodes=T)
pictureName <- xpathSApply(doc,"//h1[@itemprop='name']", xmlValue)
date <- xpathSApply(doc, "//span[@itemprop='dateCreated']", xmlValue)
author <- xpathSApply(doc, "//a[@itemprop='author']", xmlValue)
style <- xpathSApply(doc, "//span[@itemprop='style']", xmlValue)
genre <- xpathSApply(doc, "//span[@itemprop='genre']", xmlValue)
pictureName
date
author
style
genre
Каждый совет, как это сделать, будет оценен по достоинству!
Ответ №1:
Кажется, это работает.
library(XML)
library(httr)
url <- "http://www.wikiart.org/en/claude-monet/mode/all-paintings-by-alphabet/"
hrefs <- list()
for (i in 1:23) {
response <- GET(paste0(url,i))
doc <- content(response,type="text/html")
hrefs <- c(hrefs,doc["//p[@class='pb5']/a/@href"])
}
url <- "http://www.wikiart.org"
xPath <- c(pictureName = "//h1[@itemprop='name']",
date = "//span[@itemprop='dateCreated']",
author = "//a[@itemprop='author']",
style = "//span[@itemprop='style']",
genre = "//span[@itemprop='genre']")
get.picture <- function(href) {
response <- GET(paste0(url,href))
doc <- content(response,type="text/html")
info <- sapply(xPath,function(xp)ifelse(length(doc[xp])==0,NA,xmlValue(doc[xp][[1]])))
}
pictures <- do.call(rbind,lapply(hrefs,get.picture))
head(pictures)
# pictureName date author style genre
# [1,] "A Corner of the Garden at Montgeron" "1877" "Claude Monet" "Impressionism" "landscape"
# [2,] "A Corner of the Studio" "1861" "Claude Monet" "Realism" "self-portrait"
# [3,] "A Farmyard in Normandy" "c.1863" "Claude Monet" "Realism" "landscape"
# [4,] "A Windmill near Zaandam" NA "Claude Monet" "Impressionism" "landscape"
# [5,] "A Woman Reading" "1872" "Claude Monet" "Impressionism" "genre painting"
# [6,] "Adolphe Monet Reading in the Garden" "1866" "Claude Monet" "Impressionism" "genre painting"
На самом деле вы были довольно близки. Ваш XPath в порядке; одна проблема заключается в том, что не все изображения содержат всю информацию (например, для некоторых страниц наборы узлов, к которым вы пытаетесь получить доступ, пусты) — обратите внимание на дату для «Ветряная мельница над Заандамом». Таким образом, код должен учитывать эту возможность.
Итак, в этом примере первый цикл захватывает значения атрибута href тегов привязки для каждой страницы (1: 23) и объединяет их в вектор длиной ~ 1300.
Для обработки каждой из этих 1300 страниц, и поскольку нам приходится иметь дело с отсутствующими тегами, проще создать вектор, содержащий строки XPath, и применить его по элементам к каждой странице. Это то, что делает функция get.picture(...)
. Последний оператор вызывает эту функцию с каждой из 1300 hrefs и связывает результат по строкам, используя do.call(rbind,...)
.
Обратите также внимание, что в этом коде используется несколько более компактная функция индексирования для объектов класса HTMLInternalDocument:, doc[xpath]
где xpath
— строка XPath. Это позволяет избежать использования xpathSApply(...)
, хотя последнее сработало бы.
Ответ №2:
Вы можете попробовать пакет Rcrawler, это параллельный веб-скребок, он может сканировать, сохранять веб-страницы и очищать их содержимое с помощью XPath.
Если вам нужно собрать всю информацию о изображениях, используйте
datapattern<-c(
"//h1/span[@itemprop='name']",
"//a[@class='artist-name']",
"//*[@id='headSection']/article/form/div[1]/div/div/div[2]/div[2]/span[2]",
"//*[@id='headSection']/article/form/div[1]/div/div/div[2]/div[3]/a/span",
"//*[@id='headSection']/article/form/div[1]/div/div/div[2]/div[4]/a/span"
)
Rcrawler(Website = "https://www.wikiart.org/", no_cores = 4, no_conn = 4, ExtractPatterns =datapattern )
Чтобы отфильтровать только изображение Клода Моне
Rcrawler(Website = "https://www.wikiart.org/", no_cores = 4, no_conn = 4, urlregexfilter ="claude-monet/([^/])*", ExtractPatterns =datapattern )
Для завершения работы сканера потребуется некоторое время, поскольку он будет проходить по всем ссылкам на веб-сайт. Однако вы можете остановить выполнение в любое время. По умолчанию очищенные данные находятся в глобальной переменной с именем DATA, другая переменная, называемая INDEX, содержит все просмотренные URL-адреса.
Если вам нужно узнать, как создать свой поисковый робот, обратитесь к этой статье.R crawler