网站抓取






4.97/5 (18投票s)
使用 Watin 进行网站抓取。

引言
本文的主要目标是演示如何使用 Watin 测试工具等测试工具抓取网页。
通常,在 ASP.NET 中使用 C# 的 HttpWebRequest
和 HttpWebResponse
方法来抓取网页。但是,人们注意到,当应用程序使用 AJAX 进行服务器端导航时,使用 HttpWebRequest
方法获取页面数据会变得非常困难(我们需要采取一些技巧来获取下一页数据)。
使用 Watin 工具可以非常轻松快速地完成同样的事情。我在这里的目的不是挑战 HttpWebRequest
和 HttpWebResponse
方法,而是展示如何使用 Watin 等测试工具有效地进行网站抓取。
背景
在本文中,我创建了一个带有类别和后续项目列表的演示网站。我将使用 Watin 等 .NET 测试工具抓取这个网站。
在这里,我使用了 NUnit、Watin 等第三方工具来演示这个例子。请参考以下每个工具的简要介绍以及进一步参考的相应 URL。
关于 Watin:Watin 是一个专为 .NET 设计的第三方 Web 应用程序测试工具。
您可以通过访问 此链接 了解更多关于此工具的信息。
关于 NUnit:NUnit 是适用于所有 .NET 语言的第三方单元测试框架。您可以通过访问 此站点 收集更多信息。
Using the Code
本文包含两个应用程序。下面提供了关于这些应用程序的简要详细信息。
第一个应用程序是在 Visual Studio 2010 (.NET 4.0) 中创建的基于 Web 的应用程序。这是一个包含类别和项目列表的演示网站。此网站需要在本地/远程服务器 IIS 上部署。
第二个应用程序是使用 Visual Studio 2010 (.NET 4.0) 和 Watin DLL 创建的基于 Windows 的类库项目。
执行此演示所需的预备软件如下:
- .NET Framework 4.0
- NUnit 2.6.2
请按照以下步骤配置 Web 应用程序:
- 将 Web 应用程序部署到您的 IIS 中,并为其分配 .NET Framework 4.0,然后检查该应用程序在您的工作站上是否运行正常。
执行以下操作以配置 Web 抓取应用程序:
- 打开此应用程序的配置文件(App.config 或 WatinWebScraping.dll.config),并根据需要更改以下配置项的值:
WebApplicationPath
:这是部署了演示网站的应用程序路径。在当前应用程序中,我已将其部署在本地主机上,
因此我提供了路径 "https:///WebApplication/CategoryListing.aspx"。应用程序将从该网站 URL 开始抓取网页。ScraperEnginePhysicalLocation
:这是托管抓取 Web 应用程序的物理位置。
我为此路径定义的值为:“D:\WebScraping\Web Scraper\WatinWebScraping\WatinWebScraping”。我使用此路径将抓取的数据存储在文本文件中。
演示 Web 应用程序的代码片段
下面简要介绍了相应页面上的代码。
- CategoryListing.aspx:仅包含类别列表,形式为超链接。
- ItemListing.aspxsting.aspx:在此页面中,我使用了 Grid View 控件,并使用了
XMLDataSource
而不是数据库(方便配置)进行页面显示。
请参考以下代码片段。
<asp:XmlDataSource ID="xmlSource" runat="server" DataFile="~/XMLDataBase/MenFashion.xml">
</asp:XmlDataSource>
<asp:GridView ID="gvItemListing" runat="server" DataSourceID="xmlSource"
AutoGenerateColumns = "false"
AllowPaging="true" PageSize="5" Width="100%" PagerSettings-Position="Bottom">
WatinWebScraper 应用程序代码片段
在这里,我将解释以下内容:
- 在应用程序中初始化 Watin 和 NUnit
- 使用 Watin 进行网站导航
- 使用 .NET 的正则表达式功能(RegEx 和 MatchCollection)从 HTML 页面源代码中获取相应数据
- 使用 NUnit 执行此应用程序
请参考以下对各部分的解释。
1) 在应用程序中初始化 Watin 和 NUnit
要使用 Watin 和 NUnit,请向 nunit.framework.dll、“Interop.SHDocVw.dll”和“WatiN.Core.dll”添加引用。
现在,在此项目中添加对“NUnit.Framework
”和“WatiN.Core
”的引用。
由于我们将使用 NUnit 来抓取此应用程序;它要求在创建类时包含“[TestFixture]
”,并在该方法顶部使用“[Test]
”和“[STAThread]
”。
您可以通过访问 此网站 获取有关这些属性的更多详细信息。
2) 使用 Watin 进行 Web 抓取
// Create an instance of Internet Explorer browser
IE ieInstance = new IE(webSitePath);
// This will open Internet Explorer browser in maximized mode
ieInstance.ShowWindow(WatiN.Core.Native.Windows.NativeMethods.WindowShowStyle.ShowMaximized);
在执行 Web 抓取时,可以使用以下代码片段将 Watin 窗口隐藏起来。目前,这段代码被注释掉了。用户也可以取消注释此代码片段。
//ieInstance.Visible = false;
// This will wait for the browser to complete loading of the page
ieInstance.WaitForComplete();
// This will store page source in categoryPageSource variable
string categoryPageSource = ieInstance.Html;
3) 使用 .NET 的正则表达式功能(RegEx 和 MatchCollection)从 HTML 页面源代码中获取相应数据
我使用正则表达式来获取类别,并进行迭代逻辑来获取相应类别中的项目,以及移动到下一页,使用正则表达式来获取相应类别项目的所有页面。
请参考以下用于类别、项目抓取和页面导航的正则表达式。
类别正则表达式
<A\S.*?class=bold\s.*?href="(?<href>.*?)"></span>
代码解释
上述正则表达式将从 CategoryListing.aspx 页面获取所有类别 URL,并在递归循环中导航。
项目正则表达式
<P\s*id=.*?>ProductID:\s*<B>(?<ProductID>.*?)</B>.*?</P>\s*.*?<P\s*id=.*?>
ProductName:\s*<B>(?<ProductName>.*?)</B>.*?</P>\s*.*?<P\s*id=.*?>
ProductPrice:\s*<B>(?<ProductPrice>.*?)</B>.*?</P>
代码解释
上述正则表达式将获取给定页面中相应项目的 ProductID
、产品名称和产品价格。
分页正则表达式
(?(?=<SPAN>.*?</SPAN>)<SPAN>(?<PageNumber>.*?)\s*</SPAN>|
<A\s*href="javascript.*?>(?<PageNumber>.*?)\s*</A>)
代码解释
上述正则表达式将从 ItemListing.aspx 页面获取相应的页面。
要在应用程序中使用此正则表达式,我使用了“System.Text.RegularExpression
”命名空间中的“RegEx
”类。RegEx
将使用不同的选项(如“RegexOptions.Compiled
”、“RegexOptions.IgnoreCase
”、“RegexOptions.IgnorePatternWhitespace
”和“RegexOptions.CultureInvariant
”)来编译相应的正则表达式模式。
请参考下面的代码片段。
// Regular expression for Category listing page
private const string _categoryRegEx = <A\S.*?class=bold\s.*?href="(?<href>.*?)"></span>
Regex categoryMatches = new Regex(_categoryRegEx, RegexOptions.Compiled |
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.CultureInvariant);
要根据正则表达式获取记录,需要使用 MatchCollection
来获取针对相应 HTML 源生成的成功匹配列表(如 #2 所示,string categoryPageSource = ieInstance.Html;
)。请参考下面的代码。
MatchCollection categoryMatchCollection = categoryMatches.Matches(categoryPageSource);
使用 for
循环获取单个匹配项的相应结果:请参考下面的代码。
foreach (Match categoryMatch in categoryMatchCollection)
如果正则表达式是基于组创建的,则使用 GroupCollection
方法获取相应结果的组。请参考下面的代码。
GroupCollection categoryGroup = categoryMatch.Groups;
GroupCollection
包含多个相关组。为了获取类别,我使用了“href
”作为组。请参考下面的代码。
string itemListingURL = Convert.ToString(categoryGroup["href"].Value);
现在,itemListingURL
变量将包含相应类别的 href
。现在 Watin 将导航到该 URL,如下所示。itemListingPath
变量包含相应类别的项目列表页面的完整路径。
ieInstance.GoTo(itemListingpath);
我使用了“WaitForComplete
”方法来等待页面加载完成。请参考下面的代码。
ieInstance.WaitForComplete();
使用上述代码,应用程序将导航到项目列表页面。对于获取项目,需要执行类似的操作。
一旦获取了相应页面上的所有项目,并且要移动到下一页,Watin 提供了 Click
事件来执行对特定页面的单击。
Click
事件也可以根据其他不同标准执行。请参考下面。
Find.ByAlt |
Find.ByClass |
Find.ByDefault |
Find.ByElement |
Find.ByExistence OfRelatedElement |
Find.ByFor |
Find.ById |
Find.ByIndex |
Find.ByLabelText |
Find.ByName |
Find.BySelector |
Find.BySrc |
Find.ByStyle |
Find.ByText |
Find.ByTextInColumn |
Find.ByTitle |
Find.ByUrl |
Find.ByValue |
您可以通过访问 此链接 了解有关上述所有标准的更多信息。
在本文中,我使用了“Find.ByText
”来按文本查找链接,然后执行 click
事件。您也可以附加
上述标准中的正则表达式。
请参考下面的代码。
// Fetches the page number of the current page.
string linkText = Convert.ToString(pagingGroup[_pageNumber].Value);
// Performs click event on the given link. For e.g if linkText contains "2" as a value
// then Watin will perform click event on this second link.
ieInstance.Link(Find.ByText(linkText)).Click();
// Wait for the operation to complete
ieInstance.WaitForComplete();
// Store the result of the page in itemListingPageSource variable
itemListingPageSource = ieInstance.Html;
一旦抓取了网页上的相应项目,当前应用程序将使用 System.IO
命名空间中的 StreamWriter
将相应项目存储在“Output.txt”中。
现在打开“Output.txt”文件,您会发现它包含 Men
、Women
和 Children
类别中的所有项目。
4) 使用 NUnit 执行此应用程序
要执行 WatinWebScraper
应用程序,需要遵循以下步骤:
- 打开 NUnit 应用程序。
- 现在点击 File --> Open Project,然后导航到 Watin Web Scraper 应用程序的 DLL 文件(“WatinWebScraping.dll”)。请参考下面的图片。
- 现在点击上图所示的“Run”按钮。您会发现应用程序将通过导航到类别来开始抓取演示 Web 应用程序,并且所有相应的项目都将存储在“Output.txt”文件中。