Я работал над этим пару недель, но безуспешно. Моя долгосрочная цель — собрать каждое изображение со следующего веб-сайта (ссылка: https://bioguide.congress.gov/search). Для начала я пытаюсь получить только одно местоположение изображения, хранящееся в свойстве img alt HTML-кода.
HTML-код показывает это
<div class = "l-grid__item l-grid__item--3/12 l-grid__item--12/12@mobile--sm l-grid__item--4/12@desktop l-grid__item--6/12@tablet"><div tabindex = "0" class = "c-card u-flex u-flex--column u-height--100% u-cursor--pointer u-bxs--dark-lg:hover c-card--@print"><div class = "u-height--100% u-width--100% u-p u-flex u-flex--centered u-mb--auto"><div aria-hidden = "true" class = "u-max-width--80% u-max-height--250px"><img alt = "/photo/66c88d1d7401a93215e0b225.jpg" class = "u-max-height--250px u-height--auto u-width--auto u-block" src = "/photo/66c88d1d7401a93215e0b225.jpg"></div></div><div class = "u-flex u-flex--column u-flex--no-shrink u-p u-bg--off-white u-fw--bold u-color--primary u-text--center u-bt--light-gray"><div class = "u-cursor--pointer u-mb--xs">AANDAHL, Fred George</div><div class = "u-fz--sm u-fw--semibold">1897 – 1966</div></div></div></div>
Я использовал следующий код R, но получаю символ (0)
library(httr)
library(rvest)
# Fetch the HTML content with a custom User-Agent
response <- GET("https://bioguide.congress.gov/search",
user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36"))
# Parse the content
page <- read_html(content(response, as = "text", encoding = "UTF-8"))
# Navigate to the div with class starting with 'l-grid__item' and extract img alt attributes
img_alt_values <- page %>%
html_nodes(xpath = "//div[starts-with(@class, 'l-grid__item')]") %>%
html_nodes(xpath = ".//img") %>%
html_attr("alt")
Может ли кто-нибудь подсказать, как мне это преодолеть?
@AllanCameron Я уже пробовал путь Rselenium, но он тоже не проложил путь вперед. Поэтому я вернулся к этому. Насколько вы уверены, что rvest здесь не подойдет?
Это возможно, но если вы посмотрите в консоль своего браузера, вы увидите, что необходимо выполнить довольно много запросов xhr для настройки запроса, который в конечном итоге вернет файл json, содержащий фактические URL-адреса изображений. Вы могли бы разобраться с этим, если у вас есть время. Нажмите F12 в браузере, откройте панель сети, очистите ее и перейдите на страницу. Вы увидите запросы, которые вам нужно будет эмулировать, чтобы получить данные.
Взглянув на сетевой трафик, можно увидеть, что данные возвращаются из API, где функция поиска страницы генерирует запрос POST с полезной нагрузкой JSON. Мы можем использовать httr2
, чтобы отправлять эти запросы и возвращать 100 записей за раз, хотя для иллюстрации я запрашиваю только 3 записи для каждого запроса ниже.
URL-адрес и полезная нагрузка:
library(httr2)
library(jsonlite)
library(tidyverse)
# API address
url <- "https://app-elastic-prod-eus2-001.azurewebsites.net/search"
# JSON payload
payload_string <- r"({
"index": "bioguideprofiles",
"aggregations": [
{
"field": "jobPositions.congressAffiliation.congress.name",
"subFields": [
"jobPositions.congressAffiliation.congress.startDate",
"jobPositions.congressAffiliation.congress.endDate"
]
},
{
"field": "jobPositions.congressAffiliation.partyAffiliation.party.name"
},
{
"field": "jobPositions.job.name"
},
{
"field": "jobPositions.congressAffiliation.represents.regionCode"
}
],
"size": 12,
"from": 0,
"sort": [
{
"_score": true
},
{
"field": "unaccentedFamilyName",
"order": "asc"
},
{
"field": "unaccentedGivenName",
"order": "asc"
},
{
"field": "unaccentedMiddleName",
"order": "asc"
}
],
"keyword": "",
"filters": {
},
"matches": [
],
"searchType": "OR",
"applicationName": "bioguide.house.gov"
}
)"
Нам нужно преобразовать полезную нагрузку в список R, чтобы мы могли изменить аргумент from
в запросе с помощью req_body_json_modify()
:
# Convert to R list
payload_list <- fromJSON(payload_string)
# Get n records of first x records
request_size <- 3L # 100 max per request
total_records <- 15L # 12953 records in database
from <- seq(1L, total_records, request_size) - 1L # Sequence of starting positions
# Generate base request
req <- request(url) |>
req_method("POST") |>
req_body_json(payload_list)
# Generate list of requests (5 requests of 3 records each)
requests <- from |>
lapply(\(n) req |> req_body_json_modify(from = n, size = request_size))
# Execute requests
responses <- req_perform_sequential(requests, on_error = "return")
# Parse responses and extract image URL
results <- resps_data(
responses,
\(r) r |>
resp_body_json(simplifyDataFrame = TRUE) |>
pluck("filteredHits") |>
select(starts_with("unaccented"), any_of("image"))
) |>
bind_rows() |>
hoist("image", "contentUrl") |>
select(-image) |>
mutate(image_url = ifelse(is.na(contentUrl), NA, paste0("https://bioguide.congress.gov/photo/", basename(contentUrl))), .keep = "unused") |>
as_tibble()
Где results
содержит URL-адреса производных изображений:
# A tibble: 15 × 4
unaccentedFamilyName unaccentedGivenName unaccentedMiddleName image_url
<chr> <chr> <chr> <chr>
1 Aandahl Fred George https://bioguide.congress.gov/photo/66c88d1d740…
2 Abbitt Watkins Moorman https://bioguide.congress.gov/photo/ad79716f164…
3 Abbot Joel NA NA
4 Abbott Amos NA NA
5 Abbott Joseph Carter https://bioguide.congress.gov/photo/39253c461f2…
6 Abbott Joseph NA https://bioguide.congress.gov/photo/43ba0fd5299…
7 Abbott Josiah Gardner https://bioguide.congress.gov/photo/470dc5df4ba…
8 Abbott Nehemiah NA NA
9 Abdnor James NA https://bioguide.congress.gov/photo/a32ba2ea44f…
10 Abel Hazel Hempel https://bioguide.congress.gov/photo/07f3a896ce1…
11 Abele Homer E. https://bioguide.congress.gov/photo/a58aa67c32f…
12 Abercrombie James NA NA
13 Abercrombie John William https://bioguide.congress.gov/photo/76a90e5795f…
14 Abercrombie Neil NA https://bioguide.congress.gov/photo/66cbb14989f…
15 Abernethy Charles Laban https://bioguide.congress.gov/photo/00ff9ca93d0…
С каждым запросом возвращается куча других данных, но вам останется разобраться со всеми ними.
В вашем ответе есть непреодолимое количество логики, которая находится за пределами моих знаний и навыков. Прискорбно осознавать, как многому еще можно научиться в R. Тем не менее, само собой разумеется, насколько мне помогает ваш ответ и время, которое вы потратили на его составление. Спасибо и очень ценю. Принимая ваш ответ.
Ссылки на изображения не отображаются в HTML-коде, возвращенном по вашему запросу
GET
. Страница, которую вы видите в своем браузере, создается динамически с использованием JavaScript. Вы могли бы воспроизвести все шаги, необходимые для получения этих ссылок, используя только http-запросы, но это было бы долго и сложно. Вероятно, будет проще использовать RSelenium или аналогичный.