对于 C# 中的网络爬虫项目,我尝试执行 Javascript 和 Ajax 来检索已爬网页面的完整页面源代码。
我正在使用需要有效 HttpWebResponse 对象的现有网络爬虫 (Abot)。因此,我不能简单地使用driver.Navigate().GoToUrl()
方法来检索页面源代码。
爬虫下载页面源代码,我想在源代码中执行现有的Javascript/Ajax。
在一个示例项目中,我尝试了以下内容,但没有成功:
WebClient wc = new WebClient();
string content = wc.DownloadString("http://www.newegg.com/Product/Product.aspx?Item=N82E16834257697");
string tmpPath = Path.Combine(Path.GetTempPath(), "temp.htm");
File.WriteAllText(tmpPath, content);
var driverService = PhantomJSDriverService.CreateDefaultService();
var driver = new PhantomJSDriver(driverService);
driver.Navigate().GoToUrl(new Uri(tmpPath));
string renderedContent = driver.PageSource;
driver.Quit();
需要以下 nuget 包才能运行示例:https://www.nuget.org/packages/phantomjs.exe/http://www.nuget.org/packages/selenium.webdriver
这里的问题是代码在 GoToUrl()
处停止,需要几分钟才能直到程序终止,甚至没有给我驱动程序。页面源。
这样做会返回正确的 HTML:
driver.Navigate().GoToUrl("http://www.newegg.com/Product/Product.aspx?Item=N82E16834257697");
string renderedContent = driver.PageSource;
但我不想下载两次数据。爬虫(Abot)下载HTML,我只想解析/渲染javascript和ajax。
谢谢!
如果不运行它,我敢打赌你需要在tmpPath之前 file:///。 那是:
WebClient wc = new WebClient();
string content = wc.DownloadString("http://www.newegg.com/Product/Product.aspx?Item=N82E16834257697");
string tmpPath = Path.Combine(Path.GetTempPath(), "temp.htm");
File.WriteAllText(tmpPath, content);
var driverService = PhantomJSDriverService.CreateDefaultService();
var driver = new PhantomJSDriver(driverService);
driver.Navigate().GoToUrl(new Uri("file:///" + tmpPath));
string renderedContent = driver.PageSource;
driver.Quit();
您可能需要允许 PhantomJS 发出任意请求。当域/协议不匹配时,请求将被阻止,就像打开本地文件时一样。
var driverService = PhantomJSDriverService.CreateDefaultService();
driverService.LocalToRemoteUrlAccess = true;
driverService.WebSecurity = false; // may not be necessary
var driver = new PhantomJSDriver(driverService);
您可能需要将其与Dave Bush的解决方案相结合:
driver.Navigate().GoToUrl(new Uri("file:///" + tmpPath));
某些资源的 URL 以 //
开头,这意味着当浏览器检索这些资源时,将使用页面的协议。读取本地文件时,将file://
此协议,在这种情况下,将找不到这些资源。必须将协议添加到本地文件才能下载所有这些资源。
File.WriteAllText(tmpPath, content.Replace('"//', '"http://'));
从您的输出中可以明显看出您使用的是 PhantomJS 1.9.8。可能是新引入的错误负责这种事情。您应该使用带有 driverService.SslProcotol = 'tlsv1'
的 PhantomJS 1.9.7 。
如果对同一域多次执行此操作,则还应启用磁盘缓存。否则,每次尝试抓取资源时都会下载资源。这可以通过driverService.DiskCache = true;
来完成