Как автоматизировать несколько запросов к форме веб-поиска, используя R - PullRequest
12 голосов
/ 22 марта 2011

Я пытаюсь узнать, как использовать RCurl (или какой-либо другой подходящий пакет R, если я ошибаюсь из-за того, что RCurl - правильный инструмент), чтобы автоматизировать процесс отправки поисковых терминов в веб-форму и размещения результатов поиска в файл данных. Конкретная проблема, над которой я работаю, заключается в следующем:

У меня есть файл данных, содержащий номер автомобильного номера (LPN) и идентификационный номер автомобиля (VIN) для нескольких автомобилей. У Калифорнийского департамента транспортных средств (DMV) есть форма поиска по веб-странице, где вы вводите LPN и последние пять цифр VIN, и он возвращает оплату сбора за лицензию транспортного средства (VLF) за 2010 или 2009 год (есть селектор для что на форме ввода, а также). (К вашему сведению: это исследовательский проект для изучения распределения VLF-платежей по марке автомобиля, модели и модельному году)

Я мог бы пройти через утомительный процесс ввода данных вручную для каждого транспортного средства, а затем вручную вводить результат в электронную таблицу. Но это 21-й век, и я хотел бы попытаться автоматизировать этот процесс. Я хочу написать сценарий, который будет отправлять каждый LPN и VIN в веб-форму DMV, а затем помещать результат (платеж VLF) в новую переменную VLF в моем файле данных, повторяя это до тех пор, пока он не достигнет конца списка. LPNs и VINs. (Кстати, веб-форма DMV здесь: https://www.dmv.ca.gov/FeeCalculatorWeb/vlfForm.do).

Мой план состоял в том, чтобы использовать getHTMLFormDescription () (в пакете RHTMLForms), чтобы узнать имена полей ввода, а затем использовать getForm () или postForm () (в пакете RCurl) для получения выходных данных. К сожалению, я застрял на самом первом шаге. Вот команда R, которую я использовал, и вывод:

> forms = getHTMLFormDescription("https://www.dmv.ca.gov/FeeCalculatorWeb/vlfForm.do")
Error in htmlParse(url, ...) : 
  File https://www.dmv.ca.gov/FeeCalculatorWeb/vlfForm.do does not exist 

К сожалению, будучи относительно новым для R и почти совершенно новым для HTTP и просмотра веб-страниц, я не уверен, что делать дальше.

Во-первых, кто-нибудь знает, почему я получаю ошибку при моем вызове getHTMLFormDescription ()? Кроме того, есть ли другой способ выяснить имена полей ввода?

Во-вторых, можете ли вы предложить пример кода, который поможет мне начать с фактической отправки LPN и VIN и получения выходных данных? Является ли getForm () или postForm () правильным подходом или я должен делать что-то еще? Если было бы полезно иметь несколько реальных комбинаций LPN-VIN для отправки, вот три:
LPN VIN
5MXH018 30135
4TOL562 74735
5CWR968 11802

Наконец, так как вы можете видеть, что я полный новичок в этом, есть ли у вас предложения о том, что мне нужно выучить, чтобы стать мастером такого рода поисков в Интернете и как его изучить (в R или на другом языке)? Были бы полезны конкретные предложения для веб-сайтов, книг, списков рассылки, других вопросов StackOverflow и т. Д.

Спасибо за вашу помощь.

Ответы [ 4 ]

5 голосов
/ 24 марта 2011

В дополнение к предложению daroczig и Rguy, вот небольшой фрагмент кода для автоматизации всего процесса извлечения данных в фрейм данных.

# construct sample data frame with lpn, vpn and years
lpn  = rep(c('5MXH018', '4TOL562', '5CWR968'), 2);
vpn  = rep(c('30135', '74735', '11802'), 2);
year = c(rep(2009, 3), rep(2010, 3));
mydf = data.frame(lpn, vpn, year);

# construct function to extract data for one record
get_data = function(df){

  library(XML);
  # root url
  root = 'http://www.dmv.ca.gov/wasapp/FeeCalculatorWeb/vlfFees.do?method=calculateVlf&su%C2%ADbmit=Determine%20VLF'

  # construct url by adding lpn, year and vpn
  u = paste(root, '&vehicleLicense=', df$lpn, '&vehicleTaxYear=', 
            df$year, '&vehicleVin=',
      df$vpn, sep = "");

  # encode url correctly
  url  = URLencode(u);

  # extract data from the right table
  data = readHTMLTable(url)[[5]];

}

# apply function to every row of mydf and return data frame of results
library(plyr)
mydata = adply(mydf, 1, get_data);

# remove junk from column names
names(mydata) = gsub(':\302\240\302\240', '', names(mydata))
4 голосов
/ 24 марта 2011

Подробности моего комментария выше:

  • Запустите Firefox с Firebug :)
  • Заполните форму одной парой нужной таблички №. и так, и нажмите «отправить» («Определить VLF»)
  • Перейдите на вкладку «Net» в Firebug и проверьте отправленный запрос на сервер, например (извините, пользовательский интерфейс на венгерском языке - но вы, я надеюсь, получите точку):

enter image description here

  • Вы можете видеть, что запрос POST был отправлен, но данные могут быть также получены с помощью запроса GET, поэтому просто щелкните правой кнопкой мыши «POST vlfFees.do» и выберите «Копировать URL со всеми параметрами», и все готово. получив необходимый URL.
  • Вы можете изменить URL-адрес, указав требуемые LPN и VIN в URL-адресе (после vehicleLicense и vehicleVin),
  • И просто вызовите измененный URL-адрес с помощью readHTMLTable из XML пакета, который предоставит вам хороший фрейм данных необходимого набора данных.

Итак:

library(XML)
datas <- readHTMLTable("http://www.dmv.ca.gov/wasapp/FeeCalculatorWeb/vlfFees.do?method=calculateVlf&su%C2%ADbmit=Determine%20VLF&vehicleLicense=5CWR968&vehicleTaxYear=2010&vehicleVin=11802")

И получите необходимые значения таблицы, как предложено @Rguy выше:

processed <- datas[[5]][[1]]
paid <- datas[[5]][[2]]
refund <- datas[[5]][[3]]

В этом базовом примере вы можете легко написать цикл для извлечения всех требуемых данных, но не будьте жадным и не выполняйте цикл без вызова режима ожидания (см .: Sys.sleep). Я получал только одну тарелку в минуту или около того, что определенно не сильно беспокоило бы сервер.

4 голосов
/ 22 марта 2011

Просто используйте http вместо https, и это должно решить вашу проблему. Вот результат, который вы получите, если попробуете это

forms = getHTMLFormDescription("http://www.dmv.ca.gov/wasapp/FeeCalculatorWeb/vlfForm.do",  
   dropButtons = TRUE)

[[1]] Форма HTML: http://search.ca.gov/search q: [Поиск по сайту DMV]

$ feeRequestForm Форма HTML: http://www.dmv.ca.gov/wasapp/FeeCalculatorWeb/vlfFees.do VehicleLicense: []
vehicleTaxYear: VehicleVin: []

Вот пример того, как заполнить форму и получить таблицу данных со спортивной страницы Yahoo.

# get form description
url   = 'http://ca.sports.yahoo.com/nhl/stats/byteam?cat=teamstats&sort=404'
forms = getHTMLFormDescription(url);

# create a function using form description, to query the url
efun  = createFunction(forms[[3]]);

# extract webpage by passing required arguments to function
page  = efun(year = 'season_2009', conference = 'Eastern');

# parse webpage and return html tree
doc   = htmlTreeParse(page, asText = T, useInternalNodes = T);

# extract table from the html tree
tab   = readHTMLTable(doc);

Я применил это к указанной вами веб-странице, но по какой-то причине элемент формы VehicleTaxYear возвращается неправильно, что приводит к ошибкам. Кто-то с более глубоким знанием HTML-форм сможет подсказать вам, как отладить эту ошибку.

Надеюсь, это полезно

EDIT. Я исправил ошибку. Это должно быть createFunction(forms[[3]]), так как нас интересует только третья форма.

2 голосов
/ 23 марта 2011

Я хотел опубликовать это как комментарий после оригинального сообщения, но мне не хватает репутации.

Я использовал URL-адрес, предоставленный @daroczig, для получения фактических данных, которые нужны eipi10, выполнив следующие действия:

datas <- readHTMLTable("http://www.dmv.ca.gov/wasapp/FeeCalculatorWeb/vlfFees.do?method=calculateVlf&su%C2%ADbmit=Determine%20VLF&vehicleLicense=5CWR968&vehicleTaxYear=2010&vehicleVin=11802")
processed <- datas[[5]][[1]]
paid <- datas[[5]][[2]]
refund <- datas[[5]][[3]]

Короче говоря, команда readHTMLTable полезна для форматирования HTML-кода.
Я второй запрос eipi10 о том, как Дарочиг получил URL.

...