html - macro - Raspado de datos del sitio web usando vba
web scraping excel (5)
Esta pregunta se hizo mucho antes. Pero pensé que la siguiente información será útil para los novatos. En realidad, puede obtener fácilmente los valores del nombre de la clase como este.
Sub ExtractLastValue()
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Top = 0
objIE.Left = 0
objIE.Width = 800
objIE.Height = 600
objIE.Visible = True
objIE.Navigate ("https://uk.investing.com/rates-bonds/financial-futures/")
Do
DoEvents
Loop Until objIE.readystate = 4
MsgBox objIE.document.getElementsByClassName("pid-8907-last")(0).innerText
End Sub
Y si eres nuevo en el raspado web, lee esta publicación de blog.
Web Scraping - Conceptos básicos
Y también hay varias técnicas para extraer datos de páginas web. Este artículo explica algunos de ellos con ejemplos.
Estoy tratando de obtener datos del sitio web: http://uk.investing.com/rates-bonds/financial-futures través de vba, como el precio en tiempo real, es decir, alemán 5 YR Bobl, US 30Y T-Bond, he intentado sobresalir consulta web pero solo raspa todo el sitio web, pero me gustaría raspar solo la tasa, ¿hay alguna manera de hacerlo?
Hay varias maneras de hacer esto. Esta es una respuesta que escribo con la esperanza de que todos los conceptos básicos de la automatización de Internet Explorer se encuentren al buscar las palabras clave "raspar datos del sitio web", pero recuerde que nada vale como su propia investigación (si no desea apegarse a códigos preescritos que no puede personalizar).
Tenga en cuenta que esta es una forma , que no prefiero en términos de rendimiento (ya que depende de la velocidad del navegador), pero eso es bueno para entender la lógica detrás de la automatización de Internet.
1) Si necesito navegar por la web, ¡necesito un navegador! Entonces creo un navegador de Internet Explorer:
Dim appIE As Object
Set appIE = CreateObject("internetexplorer.application")
2) Le pido al navegador que explore la página web de destino.
Mediante el uso de la propiedad ".Visible", decido si quiero ver el navegador haciendo su trabajo o no.
Cuando compilar el código es bueno tener
Visible = True
, pero cuando el código está funcionando para raspar datos es bueno no verlo todo el tiempo, entonces
Visible = False
.
With appIE
.Navigate "http://uk.investing.com/rates-bonds/financial-futures"
.Visible = True
End With
3) La página web necesitará algo de tiempo para cargarse. Entonces, esperaré mientras esté ocupado ...
Do While appIE.Busy
DoEvents
Loop
4) Bueno, ahora la página está cargada. Digamos que quiero eliminar el cambio del US30Y T-Bond: lo que haré es simplemente hacer clic en F12 en Internet Explorer para ver el código de la página web y, por lo tanto, usar el puntero (en círculo rojo) haré clic en el elemento que Quiero raspar para ver cómo puedo alcanzar mi propósito.
5) Lo que debo hacer es sencillo.
En primer lugar, obtendré por la propiedad ID el elemento
tr
que contiene el valor:
Set allRowOfData = appIE.document.getElementById("pair_8907")
Aquí obtendré una colección de elementos
td
(específicamente,
tr
es una fila de datos, y
td
son sus celdas. Estamos buscando el octavo, así que escribiré:
Dim myValue As String: myValue = allRowOfData.Cells(7).innerHTML
¿Por qué escribí 7 en lugar de 8? Como las colecciones de celdas comienzan desde 0, el índice del octavo elemento es 7 (8-1). Analizando brevemente esta línea de código:
-
.Cells()
me hace acceder a los elementostd
; -
innerHTML
es la propiedad de la celda que contiene el valor que buscamos.
Una vez que tenemos nuestro valor, que ahora está almacenado en la variable
myValue
, podemos cerrar el navegador IE y liberar la memoria configurándolo en Nothing:
appIE.Quit
Set appIE = Nothing
Bueno, ahora tiene su valor y puede hacer lo que quiera con él: ponerlo en una celda (
Range("A1").Value = myValue
), o en una etiqueta de un formulario (
Me.label1.Text = myValue
)
Solo me gustaría señalarle que no es así como funciona : aquí publica preguntas sobre problemas de codificación específicos, pero primero debe hacer su propia búsqueda. La razón por la que estoy respondiendo una pregunta que no muestra demasiado esfuerzo de investigación es simplemente porque la veo varias veces y, cuando aprendí a hacer esto, recuerdo que me hubiera gustado tener algo mejor soporte para comenzar. Así que espero que esta respuesta, que es solo una "entrada de estudio" y no sea la mejor / más completa solución, pueda ser un soporte para el próximo usuario que tenga su mismo problema. Porque aprendí a programar gracias a esta comunidad y me gusta pensar que tú y otros principiantes podrían usar mi opinión para descubrir el hermoso mundo de la programación.
Disfruta tu práctica;)
Modifiqué algo que estaba apareciendo un error y terminé con esto, que funcionó muy bien para extraer los datos que necesitaba:
Sub get_data_web()
Dim appIE As Object
Set appIE = CreateObject("internetexplorer.application")
With appIE
.navigate "https://finance.yahoo.com/quote/NQ%3DF/futures?p=NQ%3DF"
.Visible = True
End With
Do While appIE.Busy
DoEvents
Loop
Set allRowofData = appIE.document.getElementsByClassName("Ta(end) BdT Bdc($c-fuji-grey-c) H(36px)")
Dim i As Long
Dim myValue As String
Count = 1
For Each itm In allRowofData
For i = 0 To 4
myValue = itm.Cells(i).innerText
ActiveSheet.Cells(Count, i + 1).Value = myValue
Next
Count = Count + 1
Next
appIE.Quit
Set appIE = Nothing
End Sub
Se mencionaron otros métodos, así que reconozcamos que, al momento de escribir, estamos en el siglo XXI. Estacionemos la apertura del navegador del bus local y vuele con una solicitud XMLHTTP GET (XHR GET para abreviar).
XHR es una API en forma de un objeto cuyos métodos transfieren datos entre un navegador web y un servidor web. El objeto lo proporciona el entorno JavaScript del navegador.
Es un método rápido para recuperar datos que no requiere abrir un navegador. La respuesta del servidor se puede leer en un HTMLDocument y el proceso de capturar la tabla continuó desde allí.
En el siguiente código, la tabla es
cr1
por su id
cr1
.
En el sub auxiliar,
WriteTable
, hacemos un bucle de las columnas (etiquetas
td
) y luego las filas de la tabla (etiquetas
tr
), y finalmente atravesamos la longitud de cada fila de la tabla, celda de tabla por celda de tabla.
Como solo queremos datos de las columnas 1 y 8, se utiliza una instrucción
Select Case
para especificar qué se escribe en la hoja.
Vista de la página web de muestra:
Salida de código de muestra:
VBA:
Option Explicit
Public Sub GetRates()
Dim html As HTMLDocument, hTable As HTMLTable ''<== Tools > References > Microsoft HTML Object Library
Set html = New HTMLDocument
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", "https://uk.investing.com/rates-bonds/financial-futures", False
.setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT" ''to deal with potential caching
.send
html.body.innerHTML = .responseText
End With
Application.ScreenUpdating = False
Set hTable = html.getElementById("cr1")
WriteTable hTable, 1, ThisWorkbook.Worksheets("Sheet1")
Application.ScreenUpdating = True
End Sub
Public Sub WriteTable(ByVal hTable As HTMLTable, Optional ByVal startRow As Long = 1, Optional ByVal ws As Worksheet)
Dim tSection As Object, tRow As Object, tCell As Object, tr As Object, td As Object, r As Long, C As Long, tBody As Object
r = startRow: If ws Is Nothing Then Set ws = ActiveSheet
With ws
Dim headers As Object, header As Object, columnCounter As Long
Set headers = hTable.getElementsByTagName("th")
For Each header In headers
columnCounter = columnCounter + 1
Select Case columnCounter
Case 2
.Cells(startRow, 1) = header.innerText
Case 8
.Cells(startRow, 2) = header.innerText
End Select
Next header
startRow = startRow + 1
Set tBody = hTable.getElementsByTagName("tbody")
For Each tSection In tBody
Set tRow = tSection.getElementsByTagName("tr")
For Each tr In tRow
r = r + 1
Set tCell = tr.getElementsByTagName("td")
C = 1
For Each td In tCell
Select Case C
Case 2
.Cells(r, 1).Value = td.innerText
Case 8
.Cells(r, 2).Value = td.innerText
End Select
C = C + 1
Next td
Next tr
Next tSection
End With
End Sub
puede usar el objeto winhttprequest en lugar de Internet Explorer, ya que es bueno cargar datos excluyendo imágenes y publicidad en lugar de descargar la página web completa, incluyendo publicidad y fotos que hacen que el objeto de Internet Explorer sea pesado en comparación con el objeto winhttpRequest.