PhantomJS传递HTML字符串并返回页面源

时间:2014-04-03 15:22:50

标签: c# javascript ajax selenium phantomjs

对于C#中的Web爬虫项目,我尝试执行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()停止,并且程序终止甚至没有给我driver.PageSource需要几分钟。

这样做会返回正确的HTML:

driver.Navigate().GoToUrl("http://www.newegg.com/Product/Product.aspx?Item=N82E16834257697");
string renderedContent = driver.PageSource;

但我不想两次下载数据。爬虫(Abot)下载HTML,我只想解析/渲染javascript和ajax。

谢谢!

2 个答案:

答案 0 :(得分:2)

如果不运行它,我打赌你需要在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();

答案 1 :(得分:2)

您可能需要允许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));

某些资源的网址以//开头,这意味着当浏览器检索这些资源时会使用该网页的协议。读取本地文件时,此协议为file://,在这种情况下,不会找到这些资源。必须将协议添加到本地文件才能下载所有这些资源。

File.WriteAllText(tmpPath, content.Replace('"//', '"http://'));

从你的output可以看出你使用的是PhantomJS 1.9.8。情况可能是newly introduced bug对此类事情负责。您应该将PhantomJS 1.9.7与driverService.SslProcotol = 'tlsv1'一起使用。


如果对同一个域执行多次此操作,则还应启用磁盘缓存。否则,每次尝试刮取资源时都会下载资源。这可以使用driverService.DiskCache = true;

完成