65.9K
CodeProject 正在变化。 阅读更多。
Home

使用正则表达式从网页中抓取信息

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.17/5 (9投票s)

2007年6月7日

CPOL

3分钟阅读

viewsIcon

40428

本文描述了如何通过网页自动导航,即发送参数并自动抓取所需信息。

引言

首先,作者不对以下信息的任何滥用行为负责,例如生成对 Web 服务器的自动化请求或侵犯他人的版权。

本文讨论的问题

本文描述了如何完成以下任务。在某些情况下,您必须访问 Internet 上的某些页面并自动抓取所需信息。例如,假设您有一个网站,您必须每天自动收集有关它的不同统计信息,以便存储在您的数据库中。很可能,您的托管提供商拥有非常强大的统计信息,但您必须先登录才能访问它。其次,您可能需要从许多其他来源获取信息,例如 Google,例如关于指向您网站的外部链接(请求链接:www.yoursite.com)。为了完成此任务,您可能需要创建一个机器人,它将为您完成这项繁琐的工作。

要从任何网页抓取所需信息,请执行以下操作

  1. 获取要抓取信息的页面的 HTML 代码。
  2. 使用正确的正则表达式创建 Regex 类实例。
  3. 使用 Regex.Match(string)Regex.Matches(string) 方法来分析您的文本。

要执行第一步,请使用类似这样的代码

WebClient wc = new WebClient();
string webtext=wc.DownloadString("url of your page here"); 

但是,通常这并不简单。首先,大多数网站都有针对自动化请求的某些保护措施。其次,您很可能必须在进入正确的页面之前传递您的参数。第三,这些参数很可能使用 POST 方法而不是 GET 传递,即您将无法在 WebRequestWebClient 类的 URL 字符串中明确地编写这些参数。因此,您需要模仿用户。

模仿用户

使用 System.Windows.Forms.WebBrowser 类并创建一个 Windows Forms 应用程序来模仿用户。例如,假设您需要从您的托管提供商抓取您网站的统计信息。很可能有一个统计页面,您需要先登录。当然,密码和用户名必须使用 POST 方法传递,并且必须使用 HTTPS。请执行以下操作

//enter the data you want to pass to web page in the following way
string post_data = "login=yourlogin&password=yourpassword"; 
byte[]post_data = Encoding.UTF8.GetBytes(PostDataStr); 
string additional_headers = 
	"Content-Type: application/x-www-form-urlencoded" + Environment.NewLine; 

//Navigate to your page posting your data 
webBrowser1.Navigate("https://yourloginpage", "", post_data, additional_headers); 
//Handle Navigated event to implement further logic 
webBrowser1.Navigated += new WebBrowserNavigatedEventHandler(webBrowser1_Navigated); 

void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e) 
{ 
//From here, if everything was correct, 
//your webBrowser control has a required credentials for navigating through your pages. 
//Remove this handler for Navigate event since it is not required anymore 
webBrowser1.Navigated -=webBrowser1_Navigated; 
webBrowser1.Navigate("Final URL to navigate"); 
//Use DocumentCompleted Event to wait for the page to be completely downloaded 
//And add the handler for this event 
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler
				(webBrowser1_DocumentCompleted); 
} 

void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) 
{ 
/*Process your page using regular expressions */ 
// Remove this handler for event since it is not required now 
webBrowser1.DocumentCompleted -= webBrowser1_DocumentCompleted; 
//Navigate further if required and add another event handler for DocumentCompleted event 
webBrowser1.DocumentCompleted+=new WebBrowserDocumentCompletedEventHandler
				(webBrowser1_DocumentCompleted2); 
webBrowser1.Navigate("Next URL to Process"); 
} 

在使用此逻辑时,需要考虑两件重要的事情。首先,webBrowser 控件应放置在可见的 Form 上并且是可见的。其次,某些页面可能会多次触发 DocumentCompleted 事件,例如,如果它们使用 AJAX。例如,Google 在显示其搜索结果时会两次触发此事件。在调试模式下检查网页并实现一个简单的计数器来解决此问题。

使用正则表达式

形式上,正则表达式是一种可以被有限自动机识别的表达式。为简单起见,我们将正则表达式视为根据某些规则编写的模板。在 .NET 中,有一个特殊的命名空间 System.Text.RegularExpressions,其中包含处理正则表达式所需的所有类。可以在 MSDN here 找到正则表达式的语言元素和创建正则表达式的规则。

例如,以下代码从网页中获取所有电子邮件。

创建控制台应用程序并使用以下简单代码

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Text.RegularExpressions; 
using System.Net; 
using System.IO; 
namespace SimpleRegexExample 
{ 
class Program 
 { 
  static void Main(string[] args) 
  { 
   //Getting the HTML content of our webpage 
   WebClient wc = new WebClient(); 
   string webtext=wc.DownloadString("url of your page here"); 
   //now if everything is OK we have content 
   //Creating regular expressions for our needs 
   //Regexp class should be created with a correct regular expression for e-mail 
   Regex regexp = new Regex("(?<Email>
	\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*)"); 
   //Search content for required elements 
   MatchCollection mc = regexp.Matches(webtext); 
   //Display what was found 
   Console.WriteLine("Emails:"); 
   for (int i = 0; i < mc.Count; i++) 
   Console.WriteLine(mc[i].Groups["Email"].Value); 
   Console.ReadKey(); 
  } 
 } 
}

结论

这种方法的主要缺点是,由于 webBrowser 必须是可见的,因此您无法将其实现为 Windows 服务。但您可以执行以下操作

  1. 在表单的 Load 事件的处理程序中实现所有逻辑。
  2. 创建一个服务,该服务将在特殊用户(例如“服务用户”)的上下文中运行,该用户将使用 System.Diagnostics.Process.Start("yourWinFormApp.exe") 类在必要时执行您的 Windows.Forms 应用程序。

由于此服务将在另一个用户的上下文中运行,因此 Windows Forms 应用程序也将在此类上下文中运行,因此“真实”用户将看不到任何其他表单。

关于作者

我是 INTSPEI 的软件工程师。

访问我的 个人网页 以查看有关我和我的项目的信息。

© . All rights reserved.