从HTML获取2字符串数组....使用正则表达式?

时间:2009-11-20 06:44:48

标签: regex arrays

我正在开展个人项目以自动填写USPS Click&发货表格,然后输出参考号#和发货确认#

到目前为止,我已经能够完成整个过程,但我不能为我的生活找出如何取出Ref#(这是我的订单#)和交付确认#

基本上,对于每个打包标签,您都会在页面中显示确认HTML页面的标签。

 <tr class="smTableText">
  <td style="border-top:solid 1px #AAAAAA; padding-bottom:4px;" valign="top">
    <table cellpadding="0" cellspacing="0" border="0" style="margin:7px 0px 0px 5px;">
      <tr> 
       <td valign="top" class="mainText" width=46>1 of 1</td>  
       <td valign="top" width=21><a href="javascript:toggleMoreInfo(0)" tabindex="19"><img src="/cns/images/common/button_plus.gif" height="11" width="11" border="0" hspace="0" vspace="0" id="Img1" style="margin-right:10px;" alt=""></a></td>  
       <td valign="top" width=203><div class="mainText" style="margin-bottom:10px; height:1em; overflow:hidden;" id="Div1">FIRSTLAST NAME<BR>STREET ADDRESS<BR>CITY, STATE  ZIP5-ZIP4<div class="smTableText">email@address.net<BR>Ref#: 100000000<BR></div> </div><div class="smTableText"></div> </td> 
      </tr>
    </table>
  </td> 
  <td style="border-top:solid 1px #AAAAAA; padding-bottom:4px; padding-top:7px;" valign="top" class="smTableText"><div id="Div2" style="margin-left:7px; height:2.4em; overflow:hidden;">&nbsp;Ship Date: 11/17/09<br>&nbsp;Weight: 0lbs 9oz<br>&nbsp;From: 48506<br></div></td>
  <td style="border-top:solid 1px #AAAAAA; padding-bottom:4px; padding-right:15px; padding-top:7px;" valign="top" align="right" class="smTableText"><div class="smTableText" id="Div3" style="height:2.4em; overflow:hidden; margin-bottom:3px;">Priority Mail                      <br>Delivery Confirm.<br></div> <span style="font-weight:bold;" class="smTableText">Label Total</span></td>
  <td style="border-top:solid 1px #AAAAAA; padding-bottom:4px; padding-right:15px; padding-top:7px;" valign="top" align="right" class="smTableText"><div class="smTableText" id="Div4" style="height:2.4em; overflow:hidden; margin-bottom:3px;">$4.80<br>$0.00<br></div><span class="smTableTextbold">$4.80</span></td>
</tr>
<tr class="smTableText"> <td colspan=4 style="height:20px;" valign="top"><div class="mainText" style="margin:0px; padding:4px 8px 0px 8px; display:block; border-top:solid 1px #AAAAAA;">Delivery Confirmation&#153; Label Number: <span class="mainTextbold">0000 1111 2222 3333 4444 55</span></div></td> </tr>

我需要做的是遍历整个页面并找到“Ref#:”捕获接下来的9个字符。 然后找到下一个"Label Number: <span class="mainTextbold">"并捕获接下来的27个字符。 每对Ref#:和Label Number: <span class="mainTextbold">都应该保存到一个数组中。

我猜这个正则表达式可能是我最好的选择吗? 任何人都可以提供一个如何工作的例子。 C#首选的VB.net也可以。

更新: 正如评论中所指出的,这不是XML,而是WebBrowser控件中显示页面的HTML代码。

我自动填写每个页面,然后调用提交按钮上的点击操作进入下一页.....问题是这最后一页,我需要的数据并不是整齐地写在一个独特的标记到该字段让我从...中拉出来。

更新#2 好吧,使用给出的例子,我提出了以下内容。 看起来像很多工作来提取2个值。我猜测必须有一种更有效的方法。

   'Sub getdeliverynum(ByVal sText As String)
Sub getdeliverynum()
    Me.MainTabControl.SelectedTab = USPSsiteTAB
    WebBrowser1.Navigate("http://www.vaporstix.com/usps.html")
    While Not WebBrowser1.ReadyState = WebBrowserReadyState.Complete
        Application.DoEvents()
    End While
    Dim input As String = WebBrowser1.DocumentText
    Dim pattern As String = "Ref#: ([^<]+)[\S\s]*?Label Number: <span class=""mainTextbold"">([^<]+)"

    For Each match As Match In Regex.Matches(input, pattern)
        Dim instance As Double
        Dim ref As String = ""
        Dim track As String = ""
        instance = 0
        For Each group As Group In match.Groups
            instance = instance + 1
            If instance = 1 Then
                'do nothing this is the full string.... 
            ElseIf instance = 2 Then
                ref = group.Value
            ElseIf instance = 3 Then
                track = group.Value
            End If
        Next
        'replace with insert to db... this is for testing.
        MsgBox("Ref: " + ref + vbCrLf + "Confirmation: " + track)
    Next

End Sub

3 个答案:

答案 0 :(得分:2)

您应该使用System.xml并使用适当的解析器来完成这项工作。 Xpath甚至导航XmlDocument都可以让您实现所需目标。

Dim xpathDoc As XPathDocument
Dim xmlNav As XPathNavigator

Dim xmlNI As XPathNodeIterator
xpathDoc = New XPathDocument("c:\builder.xml")
xmlNav = xpathDoc.CreateNavigator()
xmlNI = xmlNav.Select("//span[@class='mainTextbold']")
While (xmlNI.MoveNext())
    System.Console.WriteLine(xmlNI.Current.Name + " : " + xmlNI.Current.Value)
End While

我建议您查看therethere,了解有关如何从XmlDocument

中提取信息的详细信息

span[@class='mainTextbold']这样的Xpath选择器会返回所有这些跨度。

根据Heinzi评论,您的文档似乎无效XHTML,您应该使用TidyNet将其转换为XHTML,然后解析转换结果。

答案 1 :(得分:1)

要回答原始问题,考虑到所有关于使用正则表达式“解析”HTML的强制性警告,这里有一个正如你想要的正则表达式:

Ref#: (.{9})[\S\s]*?Label Number: <span class="mainTextbold">(.{27})

反向引用\1将包含Ref#:后的9个字符,\2将包含Label number...之后的27个字符

或者,为了使其更加健壮,您也可以使用

Ref#: ([^<]+)[\S\s]*?Label Number: <span class="mainTextbold">([^<]+)

这样,正则表达式将匹配除标记后的开口尖括号以外的任何字符。如果字符串中的正则表达式根本找不到匹配项,则会导致 lot 更多回溯。根据所使用的正则表达式引擎,如果使用所有格匹配,则可以避免这种情况:

Ref#: ([^<]++)[\S\s]*?Label Number: <span class="mainTextbold">([^<]++)

我支持使用正则表达式执行此任务的基本原理:

  1. 它简单易读/维护 - 比解析代码更容易
  2. 每页只有一个匹配,没有嵌套。
  3. 这是一个自动生成的页面,因此结构是统一的。如果UPS更改了页面布局,则必须调整正则表达式,但在这种情况下您还必须调整xml解析器。

答案 2 :(得分:0)

关于提取值的更新问题:

For Each match As Match In Regex.Matches(input, pattern)
    Dim ref As String = match.Groups(1).Value
    Dim track As String = match.Groups(2).Value

    ' replace with insert to db... this is for testing.
    MsgBox("Ref: " + ref + vbCrLf + "Confirmation: " + track)
Next

(未测试的)