我正在使用一个Windows窗体应用程序。我有一个名为"tbPhoneNumber"的文本框,其中包含一个电话号码。
我想上网站http://canada411.com并在我的文本框中输入数字,输入网站文本框ID:"c411PeopleReverseWhat",然后以某种方式点击"Find"(这是属于类"c411ButtonMig"的输入)。
之后,我想检索以下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对象?我只是不想让用户看到应用程序正在网站上运行。
我做了大量的网站抓取,我会向你展示我是如何做到的。如果我太具体了,可以跳过,但这是一个常见的主题,应该具体化。
URL简化
我为此使用的库是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并在页面上突出显示某个值,则可以右键单击inspect元素。在下面显示的代码中,您可以右键单击该值并将其复制到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循环在文档中查找与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
是的,这是可能的,我已经使用selenium框架完成了这项工作,该框架旨在测试自动化。然而,它为您提供了实现这一点的工具。
在此处下载.net:http://docs.seleniumhq.org/download/