1

我正在使用 Windows 窗体应用程序。我有一个名为“tbPhoneNumber”的文本框,其中包含一个电话号码。

我想去网站http://canada411.com并输入我文本框中的数字,进入网站文本框 ID:“c411PeopleReverseWhat”,然后以某种方式发送点击“查找”(这是一个输入属于到类“c411ButtonImg”)。

之后,我想检索以下 HTML 部分的星号之间的内容:

<div id="contact" class="vcard">
        <span><h1 class="fn c411ListedName">**Full Name**</h1></span>
        <span class="c411Phone">**(###)-###-####**</span>
        <span class="c411Address">**Address**</span>
        <span class="adr">
            <span class="locality">**City**</span>
            <span class="region">**Province**</span>
            <span class="postal-code">**L#L#L#**</span>
        </span>

所以基本上我试图将数据发送到输入框中,单击输入按钮并将检索到的值存储到变量中。我想无缝地做到这一点,所以我需要做一些类似 HTTPWebRequest 的事情?还是我使用 WebBrowser 对象?我只是不希望用户看到应用程序正在网站上运行。

4

2 回答 2

7

我做了很多网站抓取,我会告诉你我是怎么做的。如果我过于具体,请随意跳过,但这是一个普遍要求的主题,应该具体说明。

网址简化

我为此使用的库是htmlagilitypack(它是一个 dll,创建一个新项目并添加对它的引用)。首先要检查的是我们是否必须采取任何特殊步骤才能使用电话号码访问页面。我搜索了约翰史密斯并找到了很多。我输入了其中 2 个结果,发现 url 格式非常简单。那些结果是..

http://www.canada411.ca/res/7056736767/John-Smith/138223109.html

http://www.canada411.ca/res/7052355273/John-Smith/172439951.html

我测试了是否可以从 url 中删除一些我不知道的值并留下电话号码。结果我可以...

http://www.canada411.ca/search/re/1/7056736767/-

http://www.canada411.ca/search/re/1/7052355273/-

通过url可以看到url和我们的电话号码中有一些静态区域。由此我们可以为 url 构造一个字符串。

Dim phoneNumber as string = "7056736767" 'this could be TextBox1.Text or whatever
Dim URL as string = "http://www.canada411.ca/search/re/1/" + phoneNumber +"/-"

使用 XPath 提取值

现在我们已经拨入了页面,让我们检查您在上面提供的 html。您需要页面中的 6 个值,因此我们现在将创建它们...

Dim FullName As String
Dim Phone As String
Dim Address As String
Dim Locality As String
Dim Region As String
Dim PostalCode As String  

如上所述,我们将使用使用Xpath的 htmlagilitypack 。很酷的一点是,一旦我们可以在 html 中找到一些唯一标识符,我们就可以使用 Xpath 来查找我们的值。我知道这可能会令人困惑,但它会变得更加清晰。

您需要的所有值都在具有类名的标签中。让我们使用 Xpath 中的类名来查找它们。

Dim FullNameXPath As String = "//*[@class='fn c411ListedName']"
Dim PhoneXPath  As String = "//*[@class='c411Phone']"
Dim AddressXPath  As String = "//*[@class='c411Address']"
Dim LocalityXPath  As String = "//*[@class='locality']"
Dim RegionXPath  As String = "//*[@class='region']"
Dim PostalCodeXPath  As String = "//*[@class='postal-code']"

本质上,我们正在查看的是一个字符串,它将通知 htmlagilitypack 要查找的内容。在我们的例子中,文本包含在我们命名的类中。XPath 有很多内容,可能需要一段时间来解释所有内容。不过附带说明...如果您使用 Google Chrome 并突出显示页面上的值,则可以右键单击检查元素。在下面出现的代码中,您可以右键单击该值并复制到 XPath!很有用。

基本 HTMLAgilityPack 模板

现在,剩下的就是连接到页面并填充这些变量。

Dim Web As New HtmlAgilityPack.HtmlWeb
Dim Doc As New HtmlAgilityPack.HtmlDocument
Doc = Web.Load(URL)
For Each nameResult As HtmlAgilityPack.HtmlNode In Doc.DocumentNode.SelectNodes(FullNameXPath)
     Msgbox(nameResult.InnerText)        
Next

在上面的示例中,我们创建了一个名为 Web 的 HtmlWeb 对象。这是我们项目的实际爬虫。然后我们定义一个 HtmlDocument,它将包含我们转换的和可搜索的页面源。所有这些都是在幕后完成的。然后我们发送 Web 以获取页面源并将其分配给我们创建的 Doc 对象。Doc 是可重用的,幸好我们只需要连接到页面一次。

for 循环在我们的 Doc 中查找与 FullNameXPath 匹配的任何节点,FullNameXPath 之前定义为用于查找名称的 XPath 值。当找到一个节点时,它被分配给 nameResult 变量,并且在循环中我们调用一个消息框来显示我们节点的内部文本。

所以当我们把它们放在一起时

完整的工作代码(截至 2013 年 2 月 17 日)

Dim phoneNumber As String = "7056736767" 'this could be TextBox1.Text or whatever
Dim URL As String = "http://www.canada411.ca/search/re/1/" + phoneNumber + "/-"
Dim FullName As String
Dim Phone As String
Dim Address As String
Dim Locality As String
Dim Region As String
Dim PostalCode As String
Dim FullNameXPath As String = "//*[@class='fn c411ListedName']"
Dim PhoneXPath As String = "//*[@class='c411Phone']"
Dim AddressXPath As String = "//*[@class='c411Address']"
Dim LocalityXPath As String = "//*[@class='locality']"
Dim RegionXPath As String = "//*[@class='region']"
Dim PostalCodeXPath As String = "//*[@class='postal-code']"
Dim Web As New HtmlAgilityPack.HtmlWeb
Dim Doc As New HtmlAgilityPack.HtmlDocument
Doc = Web.Load(URL)
For Each nameResult As HtmlAgilityPack.HtmlNode In Doc.DocumentNode.SelectNodes(FullNameXPath)
    FullName = nameResult.InnerText
    MsgBox(FullName)
Next
For Each PhoneResult As HtmlAgilityPack.HtmlNode In Doc.DocumentNode.SelectNodes(PhoneXPath)
    Phone = PhoneResult.InnerText
    MsgBox(Phone)
Next
For Each ADDRResult As HtmlAgilityPack.HtmlNode In Doc.DocumentNode.SelectNodes(AddressXPath)
    Address = ADDRResult.InnerText
    MsgBox(Address)
Next
For Each LocalResult As HtmlAgilityPack.HtmlNode In Doc.DocumentNode.SelectNodes(LocalityXPath)
    Locality = LocalResult.InnerText
    MsgBox(Locality)
Next
For Each RegionResult As HtmlAgilityPack.HtmlNode In Doc.DocumentNode.SelectNodes(RegionXPath)
    Region = RegionResult.InnerText
    MsgBox(Region)
Next
For Each postalCodeResult As HtmlAgilityPack.HtmlNode In Doc.DocumentNode.SelectNodes(PostalCodeXPath)
    PostalCode = postalCodeResult.InnerText
    MsgBox(PostalCode)
Next
于 2013-02-17T05:59:14.203 回答
1

是的,这是可能的,我已经使用selenium 框架完成了这项工作,该框架旨在测试自动化。但是,它为您提供了执行此操作的工具。

在此处下载 .net:http: //docs.seleniumhq.org/download/

于 2013-02-17T05:00:40.193 回答