12 Stimmen

Wie man mit R mehrere Anfragen an ein Web-Suchformular automatisiert

Ich versuche zu lernen, wie man RCurl (oder ein anderes geeignetes R-Paket, wenn ich falsch über RCurl ist das richtige Werkzeug) verwenden, um den Prozess der Übermittlung von Suchbegriffen zu einem Web-Formular und Platzierung der Suchergebnisse in einer Datendatei zu automatisieren. Das spezifische Problem, an dem ich arbeite, ist das folgende:

Ich habe eine Datendatei mit Kennzeichen (LPN) und Fahrzeugidentifikationsnummer (VIN) für mehrere Autos. Das California Department of Motor Vehicles (DMV) hat ein Suchformular auf seiner Website, in das man das Kennzeichen und die letzten fünf Ziffern der Fahrzeugidentifikationsnummer eingibt, und das die Zahlung der Kfz-Steuer (VLF) entweder für 2010 oder für 2009 ausgibt (auch dafür gibt es eine Auswahlmöglichkeit auf dem Eingabeformular). (Zu Ihrer Information: Dies ist für ein Forschungsprojekt, das die Verteilung der VLF-Zahlungen nach Fahrzeugmarke, Modell und Modelljahr untersucht)

Ich könnte mir die mühsame Arbeit machen, die Daten für jedes Fahrzeug manuell einzugeben und dann das Ergebnis manuell in eine Tabelle einzutippen. Aber wir leben im 21. Jahrhundert und ich möchte versuchen, den Prozess zu automatisieren. Ich möchte ein Skript schreiben, das jede Kfz-Kennnummer und jede Fahrgestellnummer an das DMV-Webformular übermittelt und dann das Ergebnis (die VLF-Zahlung) in eine neue VLF-Variable in meiner Datendatei einträgt, und zwar so lange, bis die Liste der Kfz-Kennnummern und Fahrgestellnummern vollständig ist. (Das DMV-Webformular finden Sie übrigens hier: https://www.dmv.ca.gov/FeeCalculatorWeb/vlfForm.do ).

Mein Plan war, getHTMLFormDescription() (im RHTMLForms-Paket) zu verwenden, um die Namen der Eingabefelder herauszufinden und dann getForm() oder postForm() (im RCurl-Paket) zu verwenden, um die Ausgabe abzurufen. Leider bin ich gleich beim ersten Schritt stecken geblieben. Hier ist der R-Befehl, den ich verwendet habe, und die Ausgabe:

> 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 

Da ich relativ neu in R und fast völlig neu in HTTP und Web-Scraping bin, weiß ich leider nicht, was ich als nächstes tun soll.

Erstens, weiß jemand, warum ich einen Fehler auf meinem getHTMLFormDescription() Aufruf erhalte? Oder gibt es eine andere Möglichkeit, die Namen der Eingabefelder herauszufinden?

Zweitens, können Sie einige Beispielcodes vorschlagen, die mir dabei helfen, die LPNs und VINs tatsächlich zu übermitteln und die Ausgabe abzurufen? Ist getForm() oder postForm() der richtige Ansatz oder sollte ich etwas anderes tun? Wenn es helfen würde, einige echte LPN-VIN-Kombinationen zu übermitteln, hier sind drei:
LPN VIN
5MXH018 30135
4TOL562 74735
5CWR968 11802

Da Sie sehen können, dass ich ein absoluter Anfänger bin, haben Sie Vorschläge, was ich lernen muss, um Web Scraping dieser Art zu beherrschen und wie ich es lernen kann (in R oder in einer anderen Sprache)? Spezifische Vorschläge für Websites, Bücher, Listservs, andere StackOverflow-Fragen usw. wären großartig.

Vielen Dank für Ihre Hilfe.

5voto

Ramnath Punkte 52709

Ergänzend zu den Vorschlägen von daroczig und Rguy finden Sie hier ein kurzes Stück Code, das den gesamten Prozess der Extraktion der Daten in einen Datenrahmen automatisiert.

# 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))

4voto

Ramnath Punkte 52709

Verwenden Sie einfach http anstelle von https und das sollte Ihr Problem lösen. Hier ist die Ausgabe, die Sie erhalten, wenn Sie dies versuchen

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

[[1]] HTML-Formular: http://search.ca.gov/search q :[ DMV-Site durchsuchen ]

$feeRequestForm HTML-Formular: http://www.dmv.ca.gov/wasapp/FeeCalculatorWeb/vlfFees.do vehicleLicense :[ ]
vehicleTaxYear : vehicleVin :[ ]

Hier ist ein Beispiel dafür, wie man ein Formular ausfüllt und eine Datentabelle von einer Yahoo-Sportseite erhält.

# 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);

Ich habe dies auf die von Ihnen angegebene Webseite angewendet, aber aus irgendeinem Grund wird das Formularelement VehicleTaxYear nicht korrekt zurückgegeben, was zu Fehlern führt. Jemand, der sich mit HTML-Formularen besser auskennt, kann Ihnen helfen, diesen Fehler zu beheben.

Ich hoffe, dies ist nützlich

EDIT. Ich habe einen Fehler korrigiert. Es sollte lauten createFunction(forms[[3]]) da wir nur an der dritten Form interessiert sind.

4voto

daroczig Punkte 27061

Die Einzelheiten meines obigen Kommentars:

  • Starten Sie einen Firefox mit ファイアバグ :)
  • Füllen Sie das Formular mit einem Paar der gewünschten Plattennummer und so aus, und klicken Sie auf "Submit" ("Determine VLF")
  • Klicken Sie auf "Net" Registerkarte in Firebug und überprüfen Sie die gesendete Anfrage an den Server, wie (sorry, ungarische Benutzeroberfläche - aber Sie erhalten den Punkt, den ich hoffe):

enter image description here

  • Sie können sehen, dass eine POST-Anfrage gesendet wurde, aber die Daten können auch über eine GET-Anfrage erreicht werden. Klicken Sie also mit der rechten Maustaste auf "POST vlfFees.do" und wählen Sie "URL mit allen Parametern kopieren" und schon haben Sie die gewünschte URL.
  • Sie können die URL mit der gewünschten LPN und VIN in der URL einfach ändern (nach vehicleLicense y vehicleVin ),
  • Und rufen Sie die geänderte URL einfach mit readHTMLTable de XML Paket, das Ihnen einen schönen Datenrahmen mit dem gewünschten Datensatz liefert.

Also:

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")

Und holen Sie sich die benötigten Werte aus der Tabelle, wie @Rguy oben vorgeschlagen hat:

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

Mit diesem einfachen Beispiel könnten Sie leicht eine Schleife schreiben, die alle erforderlichen Daten abruft, aber nicht gierig sein und keine Schleife ohne einen Sleep-Aufruf (siehe: Sys.sleep ). Ich würde nur einen Teller pro Minute oder so holen, was den Kellner sicher nicht sehr stören würde.

2voto

Rguy Punkte 1602

Ich wollte dies als Kommentar nach dem ursprünglichen Beitrag posten, aber ich habe nicht genug Ansehen.

Ich habe die von @daroczig angegebene URL verwendet, um die von eipi10 gewünschten Daten zu erhalten, indem ich Folgendes getan habe

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]]

Kurz gesagt, der Befehl readHTMLTable ist nützlich für die Formatierung von HTML-Code.
Ich schließe mich der Anfrage von eipi10 an, wie daroczig an die Url gekommen ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X