使用 HtmlAgilityPack 从 C# 中的网站抓取特定数据
Scraping specific pieces of data from website in C# using HtmlAgilityPack
我很想使用 HtmlAgilityPack 抓取某个嵌套 div class 的网页,其中包含带有我要提取的数据的 span 标签
我想要的元素文本的完整 XPath:
/html/body/div[2]/div/div[1]/div/table/tbody/tr/td/span
我的代码:
static void Main(string[] args)
{
HtmlAgilityPack.HtmlWeb web = new HtmlAgilityPack.HtmlWeb();
HtmlAgilityPack.HtmlDocument doc = web.Load("http://watchout4snakes.com/wo4snakes/Random/RandomParagraph");
var paragraph = doc.DocumentNode.SelectNodes("//div[@class='mainBody']//div[@class='content']//div[@class='resultContainer']" +
"//div[@class='resultBox']//table[@class='paragraphResult']").ToList();
foreach (var item in paragraph)
{
Console.WriteLine(item.InnerText);
}
}
我尝试将完整的 XPath 放入 doc.DocumentNode.SelectNodes()
以及 //*[@id='result']
的 Xpath
我的问题是它要么 returns 什么都没有,要么我在 doc.DocumentNode.SelectNodes()
行上收到一条错误消息说 Unhandled exception. System.ArgumentNullException: Value cannot be null. (Parameter 'source')
。
问题根源在于Paragraph是通过AJAX加载的,在页面加载后由JS脚本加载。如果你在浏览器中打开 Dev Tools/Network,你可以看到它。
加载的页面部分如下所示
<table class="paragraphResult">
<tr>
<td>
<span id="result"></span>
</td>
</tr>
</table>
里面什么都没有。
加载后,页面将 AJAX POST 请求发送到同一个 URL 并获取带有参数
的纯字符串
Subject1: "",
Subject2: ""
以及它在 URL-Encoded 格式中的外观
Subject1=&Subject2=
要执行模拟表单行为,您可以手动发送 POST 请求。 HtmlAgilityPack
在这里没有用,因为接收到的数据只是一个普通字符串。
class Program
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
Console.Write("Proper Noun 1: ");
string subject1 = Console.ReadLine();
Console.Write("Proper Noun 2: ");
string subject2 = Console.ReadLine();
Dictionary<string, string> parameters = new Dictionary<string, string>()
{
{ "Subject1", subject1 },
{ "Subject2", subject2 }
};
try
{
string result = await PostHTTPRequestAsync("http://watchout4snakes.com/wo4snakes/Random/RandomParagraph", parameters);
Console.WriteLine(result);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
}
private static async Task<string> PostHTTPRequestAsync(string url, Dictionary<string, string> data)
{
using (HttpContent formContent = new FormUrlEncodedContent(data))
using (HttpResponseMessage response = await client.PostAsync(url, formContent).ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
}
}
控制台输出
Proper Noun 1: test
Proper Noun 2: Whosebug
When will the bass garage Whosebug? A digest sighs test below the objective card. Why won't test finish behind a girlfriend? A heating science approaches test.
效果很好。您需要做的就是正确分析浏览器中的 HTTP 流量。 HttpClient
也是与网络交互的强大工具。
我很想使用 HtmlAgilityPack 抓取某个嵌套 div class 的网页,其中包含带有我要提取的数据的 span 标签
我想要的元素文本的完整 XPath:
/html/body/div[2]/div/div[1]/div/table/tbody/tr/td/span
我的代码:
static void Main(string[] args)
{
HtmlAgilityPack.HtmlWeb web = new HtmlAgilityPack.HtmlWeb();
HtmlAgilityPack.HtmlDocument doc = web.Load("http://watchout4snakes.com/wo4snakes/Random/RandomParagraph");
var paragraph = doc.DocumentNode.SelectNodes("//div[@class='mainBody']//div[@class='content']//div[@class='resultContainer']" +
"//div[@class='resultBox']//table[@class='paragraphResult']").ToList();
foreach (var item in paragraph)
{
Console.WriteLine(item.InnerText);
}
}
我尝试将完整的 XPath 放入 doc.DocumentNode.SelectNodes()
以及 //*[@id='result']
的 Xpath
我的问题是它要么 returns 什么都没有,要么我在 doc.DocumentNode.SelectNodes()
行上收到一条错误消息说 Unhandled exception. System.ArgumentNullException: Value cannot be null. (Parameter 'source')
。
问题根源在于Paragraph是通过AJAX加载的,在页面加载后由JS脚本加载。如果你在浏览器中打开 Dev Tools/Network,你可以看到它。
加载的页面部分如下所示
<table class="paragraphResult">
<tr>
<td>
<span id="result"></span>
</td>
</tr>
</table>
里面什么都没有。
加载后,页面将 AJAX POST 请求发送到同一个 URL 并获取带有参数
的纯字符串Subject1: "",
Subject2: ""
以及它在 URL-Encoded 格式中的外观
Subject1=&Subject2=
要执行模拟表单行为,您可以手动发送 POST 请求。 HtmlAgilityPack
在这里没有用,因为接收到的数据只是一个普通字符串。
class Program
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
Console.Write("Proper Noun 1: ");
string subject1 = Console.ReadLine();
Console.Write("Proper Noun 2: ");
string subject2 = Console.ReadLine();
Dictionary<string, string> parameters = new Dictionary<string, string>()
{
{ "Subject1", subject1 },
{ "Subject2", subject2 }
};
try
{
string result = await PostHTTPRequestAsync("http://watchout4snakes.com/wo4snakes/Random/RandomParagraph", parameters);
Console.WriteLine(result);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
}
private static async Task<string> PostHTTPRequestAsync(string url, Dictionary<string, string> data)
{
using (HttpContent formContent = new FormUrlEncodedContent(data))
using (HttpResponseMessage response = await client.PostAsync(url, formContent).ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
}
}
控制台输出
Proper Noun 1: test
Proper Noun 2: Whosebug
When will the bass garage Whosebug? A digest sighs test below the objective card. Why won't test finish behind a girlfriend? A heating science approaches test.
效果很好。您需要做的就是正确分析浏览器中的 HTTP 流量。 HttpClient
也是与网络交互的强大工具。