使用正则表达式从网页中抓取信息
本文描述了如何通过网页自动导航,即发送参数并自动抓取所需信息。
引言
首先,作者不对以下信息的任何滥用行为负责,例如生成对 Web 服务器的自动化请求或侵犯他人的版权。
本文讨论的问题
本文描述了如何完成以下任务。在某些情况下,您必须访问 Internet 上的某些页面并自动抓取所需信息。例如,假设您有一个网站,您必须每天自动收集有关它的不同统计信息,以便存储在您的数据库中。很可能,您的托管提供商拥有非常强大的统计信息,但您必须先登录才能访问它。其次,您可能需要从许多其他来源获取信息,例如 Google,例如关于指向您网站的外部链接(请求链接:www.yoursite.com)。为了完成此任务,您可能需要创建一个机器人,它将为您完成这项繁琐的工作。
要从任何网页抓取所需信息,请执行以下操作
- 获取要抓取信息的页面的 HTML 代码。
- 使用正确的正则表达式创建
Regex
类实例。 - 使用
Regex.Match(string)
或Regex.Matches(string)
方法来分析您的文本。
要执行第一步,请使用类似这样的代码
WebClient wc = new WebClient();
string webtext=wc.DownloadString("url of your page here");
但是,通常这并不简单。首先,大多数网站都有针对自动化请求的某些保护措施。其次,您很可能必须在进入正确的页面之前传递您的参数。第三,这些参数很可能使用 POST
方法而不是 GET
传递,即您将无法在 WebRequest
或 WebClient
类的 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 服务。但您可以执行以下操作
- 在表单的
Load
事件的处理程序中实现所有逻辑。 - 创建一个服务,该服务将在特殊用户(例如“服务用户”)的上下文中运行,该用户将使用
System.Diagnostics.Process.Start("yourWinFormApp.exe")
类在必要时执行您的Windows.Forms
应用程序。
由于此服务将在另一个用户的上下文中运行,因此 Windows Forms 应用程序也将在此类上下文中运行,因此“真实”用户将看不到任何其他表单。
关于作者
我是 INTSPEI 的软件工程师。
访问我的 个人网页 以查看有关我和我的项目的信息。