【发布时间】:2019-06-12 19:07:23
【问题描述】:
我正在尝试从一个网站收集数据,该网站存储有关美国车辆事故的信息。为此,我需要遍历网站上的所有案例并将表格存储在 Excel 工作表中,以便我可以重新格式化这些数据以接收所有列出的事故的 CSV。
我从用户“QHarr”(再次感谢您)那里获得了大部分代码,到目前为止,代码工作正常,并使用 .querySelectorAll("table") 收集所有数据。不幸的是,代码似乎在特定情况下两次获取相同的信息。我认为这样做的原因是某些表嵌套在其他表中,因此嵌套表被复制两次到工作表(有时甚至以不同的格式)。我尝试通过添加检查某些关键字但未成功的 if 条件来解决此问题。
代码如下:
Option Explicit
Public Sub GetTables()
Dim sResponse As String, html As HTMLDocument, clipboard As Object, ws As Worksheet
Dim initialLinksURL As String, i As Long, j As Long, newURL As String
Set ws = ThisWorkbook.Worksheets(1)
Set clipboard = GetObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
Set html = New HTMLDocument
initialLinksURL = "https://crashviewer.nhtsa.dot.gov/LegacyCDS/Search"
'Application.ScreenUpdating = False
Dim ie As Object, caseLinks As Object
Set ie = CreateObject("InternetExplorer.Application")
With ie
.Visible = False
.Navigate2 initialLinksURL
While .Busy Or .readyState < 4: DoEvents: Wend
.document.getElementById("btnSubmit1").Click
While .Busy Or .readyState < 4: DoEvents: Wend
Set caseLinks = .document.querySelectorAll("[href*='CaseID=']")
Dim linksAndIds()
ReDim linksAndIds(1 To caseLinks.Length, 1 To 2)
For i = 0 To caseLinks.Length - 1
linksAndIds(i + 1, 1) = caseLinks.Item(i)
linksAndIds(i + 1, 2) = Replace$(caseLinks.Item(i), "https://crashviewer.nhtsa.dot.gov/nass-cds/CaseForm.aspx?xsl=main.xsl&CaseID=", vbNullString)
Next
For i = LBound(linksAndIds, 1) To UBound(linksAndIds, 1)
newURL = "https://crashviewer.nhtsa.dot.gov/nass-cds/CaseForm.aspx?ViewText&CaseID=" & linksAndIds(i, 2) & "&xsl=textonly.xsl&websrc=false" '"https://crashviewer.nhtsa.dot.gov/nass-cds/CaseForm.aspx?ViewPage&xsl=Case.xsl&tab=Crash&form=CaseForm&baseNode=&vehnum=-1&occnum=-1&pos=-1&pos2=-1&websrc=true&title=Crash%20Overview%20-%20Summary&caseid=" & linksAndIds(i, 2) & "&year=&fullimage=false"
.Navigate2 newURL
While .Busy Or .readyState < 4: DoEvents: Wend
Dim tables As Object
Set tables = .document.querySelectorAll("table")
For j = 0 To tables.Length - 1
clipboard.SetText tables.Item(j).outerHTML
If Not CBool(InStr(tables.Item(j).outerHTML, "Scene Photos")) And Not CBool(InStr(tables.Item(j).outerHTML, "Image ID: ")) _
And Not CBool(InStr(tables.Item(j).outerHTML, "Braint")) _
And UBound(Split(tables.Item(j).outerHTML, "subtable")) <= 1 Then 'no images and avoid duplicate tables
clipboard.PutInClipboard
ws.Cells(LastRow(ws) + 2, 1).PasteSpecial
End If
Next
Next
.Quit
End With
'Application.ScreenUpdating = True
End Sub
'https://www.rondebruin.nl/win/s9/win005.htm
Public Function LastRow(ByVal sh As Worksheet) As Long
On Error Resume Next
LastRow = sh.Cells.Find(What:="*", _
After:=sh.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
End Function
我正在考虑获取最深的 HTML 元素/子元素,但我不知道如何做到这一点,或者这是否能解决我的问题。
非常感谢。
【问题讨论】:
-
如何填充结果以及你想从@Noco那里解析什么?
-
你能提供一个写出重复信息的示例网址吗?
-
@QHarr :例如,如果我们查看第一个案例(案例 ID:2004-04-089),代码复制了以标题“测量(以厘米为单位)”开头的表格。此外,表格“车辆 1 乘员 1 - 伤害代码”以两种不同的格式复制。
-
我去看看。你运行下面的代码是否遇到了同样的问题?
-
@SIM :基本上,我想要一个 CSV 文件,它将相同类型的信息分组到列中。例如,如果有一个包含车辆属性(例如质量、尺寸等)的表格,我希望所有案例的信息都列在同一列中,以便数据具有可比性并可以进行评估。这能回答你的问题吗?
标签: html vba web-scraping html-table