Очистка участка Ассамблеи Невады / Сената с R + V8 - PullRequest
1 голос
/ 23 октября 2019

Я пытаюсь почистить веб-страницы законодательного органа штата Невада (то есть таблицы членов собрания и сенаторов и их личных страниц ), и меня постепенно сводят с ума. Это выглядит просто: есть таблицы, которые присутствуют в HTML при изучении исходного кода. За исключением наилучшего, я могу сказать, что они создаются с использованием запросов Javascript, и это ново для меня.

Я пробовал некоторые обходные пути, например этот вопрос обмена стека , ноне могу найти ни одного. Я сейчас пытаюсь следовать указаниям здесь и здесь безрезультатно. Это для платного концерта, и я трачу слишком много оплачиваемых часов. Я собираюсь просто вручную заполнить данные штопки, но я полагаю, что изучение этого сейчас может спасти будущие головные боли.

Когда я ищу скрипты, я нахожу 11, но только первый и последний имеют текст внутриих. Когда я пытаюсь вызвать последний скрипт с помощью ct $ eval (), я получаю сообщение об ошибке «Ошибка в context_eval (объединение (src), закрытый $ context): ReferenceError: $ не определено»

> read_html(link) %>% html_nodes("script") {xml_nodeset (11)} [1]
<script type="text/javascript">
  \
  r\ n
  var SiteTitle = "Legislator I ... [2] < script src = "/App/Legislator/A/Scripts/jquery-1.8.1.js" >
</script>
[3]
<script src="/App/Legislator/A/Scripts/DataTables/jquery.dataTables.js">
  ...[4] < script src = "/App/Legislator/A/Scripts/jquery.fancybox.pack.js" >
</script>
[5]
<script src="/App/Legislator/A/Scripts/jquery.fancybox-buttons.js">
  < /scr ... [6] < script src = "/App/Legislator/A/Scripts/jquery.fancybox-media.js" >
</script>
[7]
<script src="/App/Legislator/A/Scripts/jquery.fancybox-thumbs.js"></script>
[8]
<script src="/App/Legislator/A/Scripts/bootstrap.js"></script>
[9]
<script src="/App/Legislator/A/Scripts/DateFormat.js"></script>
[10]
<script src="/App/Legislator/A/Scripts/LCB.js"></script>
[11]
<script type="text/javascript">
  \
  r\ n\ t $(function() {\
        r\ n\ t\ t //console ...

#Loading both the required libraries
library(rvest)
library(V8)
#URL with js-rendered content to be scraped
link <- "https://www.leg.state.nv.us/App/Legislator/A/Senate/Current/1"
#Read the html page content and extract all javascript codes that are inside a list
jscript <- read_html(link) %>% html_nodes('script') %>% html_text()
# Create a new v8 context
ct <- v8()
#parse the html content from the js output and print it as text
read_html(ct$eval(jscript[11])) %>% 
  html_text()

Я застрял! предложения приветствуются!

1 Ответ

1 голос
/ 23 октября 2019

Данные для целевой страницы и личных страниц динамически поступают из вызовов API, которые можно найти на вкладке сети.

Целевая страница получает информацию из следующего вызова и возвращает все необходимое в виде json

https://www.leg.state.nv.us/App/Legislator/A/api/Current/Legislator?house=Assembly

Если вы перебираете возвращенный список, вы можете извлечь MemberID для каждого члена и объединить его во второй вызов API, который возвращает всю информацию с их личной страницы.

`https://www.leg.state.nv.us/App/Legislator/A/api/Current/Legislator?id={member["MemberID"]}`

Вы можете сделать это paste0 в R.

Я создаю словарь со сценарием, ниже которого в качестве ключей указывается номер района, связанный с этим ключом, и вся информация о члене изцелевая страница в качестве связанного значения вместе с json, возвращаемым из 'personal page'.


R версия:

library(jsonlite)
library(collections)

members <- jsonlite::read_json('https://www.leg.state.nv.us/App/Legislator/A/api/Current/Legislator?house=Assembly')
d <- Dict(items = NULL)

for(member in members){
  district <- member$DistrictNbr
  personal_url <- paste0('https://www.leg.state.nv.us/App/Legislator/A/api/Current/Legislator?id=', member$MemberID)
  personal_data <- jsonlite::read_json(personal_url)
  d$set(district, c(member,personal_data))
}

print(d$keys()) #dict keys
print(d$get("1")) #district 1
print(d$get("1")("legislatorCareerInfo")) #example personal info

Py

import requests

results = {}

with requests.Session() as s:
    r = s.get('https://www.leg.state.nv.us/App/Legislator/A/api/Current/Legislator?house=Assembly').json()
    for member in r:
        district = member['DistrictNbr']
        results[district] = member
        r2 = s.get(f'https://www.leg.state.nv.us/App/Legislator/A/api/Current/Legislator?id={member["MemberID"]}').json()
        results[district]['personal_page'] = r2
print(results)

Рекомендации:

  1. сборник пакетов
...