Javascript 通过在PhantomJS中循环来抓取多个URL

Javascript 通过在PhantomJS中循环来抓取多个URL,javascript,for-loop,web-scraping,phantomjs,Javascript,For Loop,Web Scraping,Phantomjs,我正在使用PhantomJS刮取一些网站,因此用r提取信息。我正在学习教程。对于单个页面来说,一切都很好,但我找不到任何关于如何自动处理多个页面的简单教程。 到目前为止,我的实验是: var countries = [ "Albania" ,"Afghanistan"]; var len = countries.length; var name1 = ".html"; var add1 = "http://www.kluwerarbitration.com/CommonUI/BITs.aspx?

我正在使用PhantomJS刮取一些网站,因此用r提取信息。我正在学习教程。对于单个页面来说,一切都很好,但我找不到任何关于如何自动处理多个页面的简单教程。 到目前为止,我的实验是:

var countries = [ "Albania" ,"Afghanistan"];
var len = countries.length;
var name1 = ".html";
var add1 = "http://www.kluwerarbitration.com/CommonUI/BITs.aspx?country=";
var country ="";
var name ="";
var add="";


for (i=1; i <= len; i++){

    country = countries[i]
    name = country.concat(name1)
    add = add1.concat(name1)

    var webPage = require('webpage');
    var page = webPage.create();

    var fs = require('fs');
    var path = name

    page.open(add, function (status) {
        var content = page.content;
        fs.write(path,content,'w')
        phantom.exit();
    });

}
var国家=[“阿尔巴尼亚”、“阿富汗”];
var len=国家/地区长度;
var name1=“.html”;
变量add1=”http://www.kluwerarbitration.com/CommonUI/BITs.aspx?country=";
var country=“”;
var name=“”;
var add=“”;

对于(i=1;i而言,主要问题似乎是您退出得太早。您在一个循环中创建了多个
page
实例。由于PhantomJS是异步的,因此对
page.open()
的调用立即存在,并执行下一个for循环迭代

for循环非常快,但web请求很慢。这意味着在加载第一个页面之前,循环就已经完全执行。这也意味着加载的第一个页面也将退出PhantomJS,因为您在这些
page.open()中调用了
phantom.exit()
callbacks。我怀疑由于某种原因,第二个URL速度更快,因此总是被写入

var countFinished = 0, 
    maxFinished = len;
function checkFinish(){
    countFinished++;
    if (countFinished + 1 === maxFinished) {
        phantom.exit();
    }
}

for (i=1; i <= len; i++) {
    country = countries[i]
    name = country.concat(name1)
    add = add1.concat(country)

    var webPage = require('webpage');
    var page = webPage.create();

    var fs = require('fs');
    var path = name

    page.open(add, function (status) {
        var content = page.content;
        fs.write(path, content,'w')
        checkFinish();
    });
}
由于JavaScript具有函数级作用域,因此需要使用IIFE在
page.open()
回调中保留对正确
page
实例的引用。有关更多信息,请参阅此问题:


如果你不想事后清理,那么你应该在所有这些URL上使用相同的
页面
实例。我在这里已经有了这样做的答案:

鉴于我对js的知识非常有限,我考虑了一个解决问题的方法。我仍然对正确解决问题感兴趣,但我预见这将有助于解决问题这是相当长的一段时间

目前,我在R中做了一些实验,得到了我想要的结果。我没有在js中运行循环,而是使用R编写了多个单独的js代码,这样就绕过了“phantomjs是异步问题”

诀窍在于使用参数quote=F的write.table导出js代码块,并使用.js作为文件扩展名,以便正确地将其识别为js文件。我想这种解决方法对其他类似任务的适用性有限,但可能会对某些人有所帮助。非常感谢您的评论

countries <- c("Afghanistan", "Albania", "Algeria")

for (i in unique(countries)){

  df <- data.frame(lines=character(11), 
                   stringsAsFactors=FALSE) 
  outputline <- paste("var path = '", i, ".html'" , sep="")
  inputline <- paste("page.open('http://www.kluwerarbitration.com/CommonUI/BITs.aspx?country=", i ,"', function (status) {", sep="")
  df$lines[1] <- "var webPage = require('webpage');"
  df$lines[2] <- "var page = webPage.create();"
  df$lines[3] <- "var fs = require('fs');"
  df$lines[4] <- ""
  df$lines[5] <- outputline
  df$lines[6] <- ""
  df$lines[7] <- inputline
  df$lines[8] <-  "  var content = page.content;"
  df$lines[9] <-  "  fs.write(path,content,'w')"
  df$lines[10] <-  "  phantom.exit();"
  df$lines[11] <-  "});"

  write.table(df, paste(i, ".js", sep = ""), sep=" ", quote=F, row.names=F, col.names=F)

}

library(rvest)
library(stringr)
library(plyr)
library(dplyr)
library(ggvis)
library(knitr)
options(digits = 4)


 #run all individual javascript files
index <- 1
for (i in countries){
 javacode <- paste0("./phantomjs", sep=" ",  countries, ".js")
  system(javacode[index])
 index <- index + 1
}

我会给出与您链接到的国家/地区相同的答案。也许您应该说明哪里出了问题。由于PhantomJS是异步的,您不能以一种简单的方式使用循环。顺便说一句,您还没有说这段代码出了什么问题。它不起作用的事实几乎没有足够的信息让我们确定哪里出了问题。我我对此很陌生,主要的问题是我不太了解。在运行代码时,我似乎没有遇到任何错误,脚本只为第二个国家创建了一个html文件,其中包含页面上的所有信息,我感兴趣的小表格除外。我将继续阅读其他问题,非常感谢感谢,这这帮了大忙!我会等着接受答案,直到我有了一个工作代码。我的代码中有一个愚蠢的错误:add=add1.concat(name1)是错误的,它应该是add=add1.concat(country)。这就是我在评论中提到的唯一一个被删除的网页缺少信息的原因。我将尝试编辑它
countries <- c("Afghanistan", "Albania", "Algeria")

for (i in unique(countries)){

  df <- data.frame(lines=character(11), 
                   stringsAsFactors=FALSE) 
  outputline <- paste("var path = '", i, ".html'" , sep="")
  inputline <- paste("page.open('http://www.kluwerarbitration.com/CommonUI/BITs.aspx?country=", i ,"', function (status) {", sep="")
  df$lines[1] <- "var webPage = require('webpage');"
  df$lines[2] <- "var page = webPage.create();"
  df$lines[3] <- "var fs = require('fs');"
  df$lines[4] <- ""
  df$lines[5] <- outputline
  df$lines[6] <- ""
  df$lines[7] <- inputline
  df$lines[8] <-  "  var content = page.content;"
  df$lines[9] <-  "  fs.write(path,content,'w')"
  df$lines[10] <-  "  phantom.exit();"
  df$lines[11] <-  "});"

  write.table(df, paste(i, ".js", sep = ""), sep=" ", quote=F, row.names=F, col.names=F)

}

library(rvest)
library(stringr)
library(plyr)
library(dplyr)
library(ggvis)
library(knitr)
options(digits = 4)


 #run all individual javascript files
index <- 1
for (i in countries){
 javacode <- paste0("./phantomjs", sep=" ",  countries, ".js")
  system(javacode[index])
 index <- index + 1
}