像浏览器一样检索网页内容
Retrieve web page content like a browser
在了解了一些不同的技术之后,我想用 UWP+NoSQL 做一个小项目。我想做一个小型 UWP 应用程序,它可以抓取星座运势并每天早上在我的 raspberry Pi 上显示它。
所以我选择了 WebClient
,然后执行以下操作:
WebClient client = new WebClient();
client.Headers[HttpRequestHeader.UserAgent] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2";
string downloadString = client.DownloadString("http://www.horoscope.com/us/horoscopes/general/horoscope-general-daily-today.aspx?sign=2");
但它似乎检测到这个请求不是来自浏览器,因为有趣的部分不在内容中(当我检查浏览器时,它在初始 HTML , 根据 fiddler).
我也尝试过使用 ScrapySharp,但我得到了相同的结果。知道为什么吗?
(我已经完成了UWP部分,所以我不想因为它被检测为"bot"而改变我个人项目的主题)
编辑
看来我还不够清楚。问题**不是*我无法解析 HTML,问题是我在使用 ScrapySharp/WebClient
时没有收到预期的 HTML
EDIT2
这是我检索到的内容:http://pastebin.com/sXi4JJRG
而且,我没有得到(例如)"Star ratings by domain" + 每个星星的相关图片
您可以使用下面显示的代码片段阅读网页的全部内容:
internal static string ReadText(string Url, int TimeOutSec)
{
try
{
using (HttpClient _client = new HttpClient() { Timeout = TimeSpan.FromSeconds(TimeOutSec) })
{
_client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("text/html"));
using (HttpResponseMessage _responseMsg = _client.GetAsync(Url))
{
using (HttpContent content = _responseMsg.Content)
{
return content.ReadAsString();
}
}
}
}
catch { throw; }
}
或者用简单的方式:
public static void DownloadString (string address)
{
WebClient client = new WebClient ();
string reply = client.DownloadString (address);
Console.WriteLine (reply);
}
(回复:https://msdn.microsoft.com/en-us/library/fhd1f0sw(v=vs.110).aspx)
是的,WebClient 不会给您预期的结果。许多站点都有用于加载内容的脚本。所以要模拟浏览器,您还应该 运行 页面脚本。
我从来没有做过类似的事情,所以我的回答纯理论。
解决您需要"headless browser"的问题。
我知道两个项目(我从来没有尝试过):
前段时间我用过 http://www.nrecosite.com/phantomjs_wrapper_net.aspx 它运行良好,正如 Anton 提到的那样,它是一个无头浏览器。也许会有一些帮助。
我想知道您希望 'in the content' 看到的 'interesting part' 是否都是图像?您是否知道必须单独检索任何图像这一事实? html 页面包含 <image.../>
标签这一事实并没有神奇地显示它们。正如您在 Fiddler 中看到的那样,在检索页面后,浏览器会检索所有图像、样式表、javascript 以及指定但未包含在页面中的所有其他项目。 (您可能需要清除浏览器缓存才能看到这种情况...)
好的,我想我知道发生了什么:我将实际输出(没有花哨的用户代理字符串)与您的 pastebin 提供的输出进行了比较,发现了一些有趣的东西。在第 213 行,您的 pastebin 具有:
<li class="dropdown"><a href="/us/profiles/zodiac/index-profile-zodiac-sign.aspx" class="dropdown-toggle" data-hov...ck">Forecast Tarot Readings</div>
注意接近尾声的 data-hov...ck
。在实际输出中,这是:
<li class="dropdown"><a href="/us/profiles/zodiac/index-profile-zodiac-sign.aspx" class="dropdown-toggle" data-hover="dropdown" data-toggle="link">Astrology</a>
后面是大约 600 行代码,包括前面提到的 'interesting part'。在第 814 行,它说:
<div class="bot-explore-col-subtitle f14 blocksubtitle black">Forecast Tarot Readings</div>
以黑色的 ck 开头,与 pastebin 输出的其余部分相匹配。所以,要么是 pastebin 压缩了输出,要么是原始输出。
我创建了一个新的控制台应用程序,插入了您的代码,并得到了我预期的结果,包括您似乎错过的 html 600 行:
static void Main(string[] args)
{
WebClient client = new WebClient();
client.Headers[HttpRequestHeader.UserAgent] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2";
string downloadString = client.DownloadString("http://www.horoscope.com/us/horoscopes/general/horoscope-general-daily-today.aspx?sign=2");
File.WriteAllText(@"D:\Temp\source-mywebclient.html", downloadString);
}
我的 WebClient
来自 System.Net
。更改 UserAgent 几乎没有任何效果,几个链接有点不同。
因此,总结一下:您的问题与初始获取后动态插入的内容无关,但可能与 webclient 结合 UWP 有关。网站上还有一个关于 webclient 和 UWP 的问题: 指出您应该使用 HttpClient。也许这是一个解决方案?
在了解了一些不同的技术之后,我想用 UWP+NoSQL 做一个小项目。我想做一个小型 UWP 应用程序,它可以抓取星座运势并每天早上在我的 raspberry Pi 上显示它。
所以我选择了 WebClient
,然后执行以下操作:
WebClient client = new WebClient();
client.Headers[HttpRequestHeader.UserAgent] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2";
string downloadString = client.DownloadString("http://www.horoscope.com/us/horoscopes/general/horoscope-general-daily-today.aspx?sign=2");
但它似乎检测到这个请求不是来自浏览器,因为有趣的部分不在内容中(当我检查浏览器时,它在初始 HTML , 根据 fiddler).
我也尝试过使用 ScrapySharp,但我得到了相同的结果。知道为什么吗?
(我已经完成了UWP部分,所以我不想因为它被检测为"bot"而改变我个人项目的主题)
编辑
看来我还不够清楚。问题**不是*我无法解析 HTML,问题是我在使用 ScrapySharp/WebClient
时没有收到预期的 HTMLEDIT2
这是我检索到的内容:http://pastebin.com/sXi4JJRG
而且,我没有得到(例如)"Star ratings by domain" + 每个星星的相关图片
您可以使用下面显示的代码片段阅读网页的全部内容:
internal static string ReadText(string Url, int TimeOutSec)
{
try
{
using (HttpClient _client = new HttpClient() { Timeout = TimeSpan.FromSeconds(TimeOutSec) })
{
_client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("text/html"));
using (HttpResponseMessage _responseMsg = _client.GetAsync(Url))
{
using (HttpContent content = _responseMsg.Content)
{
return content.ReadAsString();
}
}
}
}
catch { throw; }
}
或者用简单的方式:
public static void DownloadString (string address)
{
WebClient client = new WebClient ();
string reply = client.DownloadString (address);
Console.WriteLine (reply);
}
(回复:https://msdn.microsoft.com/en-us/library/fhd1f0sw(v=vs.110).aspx)
是的,WebClient 不会给您预期的结果。许多站点都有用于加载内容的脚本。所以要模拟浏览器,您还应该 运行 页面脚本。 我从来没有做过类似的事情,所以我的回答纯理论。
解决您需要"headless browser"的问题。 我知道两个项目(我从来没有尝试过):
前段时间我用过 http://www.nrecosite.com/phantomjs_wrapper_net.aspx 它运行良好,正如 Anton 提到的那样,它是一个无头浏览器。也许会有一些帮助。
我想知道您希望 'in the content' 看到的 'interesting part' 是否都是图像?您是否知道必须单独检索任何图像这一事实? html 页面包含 <image.../>
标签这一事实并没有神奇地显示它们。正如您在 Fiddler 中看到的那样,在检索页面后,浏览器会检索所有图像、样式表、javascript 以及指定但未包含在页面中的所有其他项目。 (您可能需要清除浏览器缓存才能看到这种情况...)
好的,我想我知道发生了什么:我将实际输出(没有花哨的用户代理字符串)与您的 pastebin 提供的输出进行了比较,发现了一些有趣的东西。在第 213 行,您的 pastebin 具有:
<li class="dropdown"><a href="/us/profiles/zodiac/index-profile-zodiac-sign.aspx" class="dropdown-toggle" data-hov...ck">Forecast Tarot Readings</div>
注意接近尾声的 data-hov...ck
。在实际输出中,这是:
<li class="dropdown"><a href="/us/profiles/zodiac/index-profile-zodiac-sign.aspx" class="dropdown-toggle" data-hover="dropdown" data-toggle="link">Astrology</a>
后面是大约 600 行代码,包括前面提到的 'interesting part'。在第 814 行,它说:
<div class="bot-explore-col-subtitle f14 blocksubtitle black">Forecast Tarot Readings</div>
以黑色的 ck 开头,与 pastebin 输出的其余部分相匹配。所以,要么是 pastebin 压缩了输出,要么是原始输出。
我创建了一个新的控制台应用程序,插入了您的代码,并得到了我预期的结果,包括您似乎错过的 html 600 行:
static void Main(string[] args)
{
WebClient client = new WebClient();
client.Headers[HttpRequestHeader.UserAgent] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2";
string downloadString = client.DownloadString("http://www.horoscope.com/us/horoscopes/general/horoscope-general-daily-today.aspx?sign=2");
File.WriteAllText(@"D:\Temp\source-mywebclient.html", downloadString);
}
我的 WebClient
来自 System.Net
。更改 UserAgent 几乎没有任何效果,几个链接有点不同。
因此,总结一下:您的问题与初始获取后动态插入的内容无关,但可能与 webclient 结合 UWP 有关。网站上还有一个关于 webclient 和 UWP 的问题: