0

所以我目前正在制作一个谷歌浏览器扩展程序,当我将一个新成绩发布到我的大学的所有课程成绩簿中时,它会通知我,所以目前我正在尝试迭代地抓取和抓取网址并将其与最后一次迭代进行比较(...),并且当我使用request()函数时(即使使用异步),函数当前返回未定义的响应和正文,并给我这个错误的其他奇怪的事情,如果我尝试console.log所有这些。request()函数返回未定义的值

这里之后,我发现了错误:

bundle.js:24 Uncaught TypeError: Cannot read property 'headers' of undefined 
    at Request._callback (bundle.js:24) 
    at self.callback (bundle.js:54273) 
    at Request.EventEmitter.emit (bundle.js:95413) 
    at Request.start (bundle.js:54842) 
    at Request.end (bundle.js:55610) 
    at end (bundle.js:54652) 
    at bundle.js:54666 
    at Item.run (bundle.js:103974) 
    at drainQueue (bundle.js:103944) 

这里是我的代码(更改URL,这样你就看不到我校的登录网址):

var Crawler = require("simplecrawler"), 
    url = require("url"), 
    cheerio = require("cheerio"), 
    request = require("request"); 

var initialURL = "https://www.fakeURL.com/"; 


var crawler = new Crawler(initialURL); 

request("https://www.fakeURL.com/", { 
    // The jar option isn't necessary for simplecrawler integration, but it's 
    // the easiest way to have request remember the session cookie between this 
    // request and the next 
    jar: true, 
    mode: 'no-cors' 
}, function(error, response, body) { 
    // Start by saving the cookies. We'll likely be assigned a session cookie 
    // straight off the bat, and then the server will remember the fact that 
    // this session is logged in as user "iamauser" after we've successfully 
    // logged in 

    crawler.cookies.addFromHeaders(response.headers["set-cookie"]); 

    // We want to get the names and values of all relevant inputs on the page, 
    // so that any CSRF tokens or similar things are included in the POST 
    // request 
    var $ = cheerio.load(body), 
     formDefaults = {}, 
     // You should adapt these selectors so that they target the 
     // appropriate form and inputs 
     formAction = $("#login").attr("action"), 
     loginInputs = $("input"); 

    // We loop over the input elements and extract their names and values so 
    // that we can include them in the login POST request 
    loginInputs.each(function(i, input) { 
     var inputName = $(input).attr("name"), 
      inputValue = $(input).val(); 

     formDefaults[inputName] = inputValue; 
    }); 

    // Time for the login request! 
    request.post(url.resolve(initialURL, formAction), { 
     // We can't be sure that all of the input fields have a correct default 
     // value. Maybe the user has to tick a checkbox or something similar in 
     // order to log in. This is something you have to find this out manually 
     // by logging in to the site in your browser and inspecting in the 
     // network panel of your favorite dev tools what parameters are included 
     // in the request. 
     form: Object.assign(formDefaults, { 
      username: "secretusername", 
      password: "secretpassword" 
     }), 
     // We want to include the saved cookies from the last request in this 
     // one as well 
     jar: true 
    }, function(error, response, body) { 
     // That should do it! We're now ready to start the crawler 
     crawler.interval = 10000 //600000 // 10 minutes 
     crawler.maxConcurrency = 1; // 1 active check at a time 
     crawler.maxDepth = 5; 
     crawler.start(); 
    }); 
}); 

crawler.on("fetchcomplete", function(queueItem, responseBuffer, response) { 
    console.log("Fetched", queueItem.url, responseBuffer.toString()); 
}); 

// crawler.interval = 600000 // 10 minutes 
// crawler.maxConcurrency = 1; // 1 active check at a time 
// crawler.maxDepth = 5; 
// 
// crawler.start(); 

一件事需要注意的是,我将'no-cors'模式添加到了我的请求中,因此,只要我测试了这一点,我就可以停止发现CORS的问题,但这可能是导致此问题的原因吗?

谢谢!

编辑:我使用Browserify在浏览器中使用require()的东西。我无法发布bundle.js中的实际代码,因为它非常长,并且不适合这里。只是想澄清一点。谢谢!

EDIT2:这里是我给什么,当我尝试做的console.log(错误):

Error: Invalid value for opts.mode 
    at new module.exports (bundle.js:108605) 
    at Object.http.request (bundle.js:108428) 
    at Object.https.request (bundle.js:97056) 
    at Request.start (bundle.js:54843) 
    at Request.end (bundle.js:55613) 
    at end (bundle.js:54655) 
    at bundle.js:54669 
    at Item.run (bundle.js:103977) 
    at drainQueue (bundle.js:103947) 
+0

试着弄清楚'error'的内容是什么,并检查'response.status'。看起来你的http请求中存在“一些错误”。如果没有更多的信息,我可以说。 – James

+0

我试着检查错误,但问题是它给了我:错误:opts.mode的值无效(原始文章中的完整跟踪)。而且我无法检查response.status,因为响应未定义。 –

+0

@OmarBaradei那么,最终的答案是否帮助你? –

回答

0

正如詹姆斯所说,如果你得到一个错误,通过登录就安慰检查错误或者你最喜欢的任何方法来显示调试信息。

如果您正在获得Cannot read property 'headers' of undefined,如您所说,response未定义,因此您的第一个回调行将失败,因为它尝试访问response.headers

这里简单调试的方法是在错误达到问题之前(因为它在那里暂停)之前,console.log(),因此您必须简单地将console.log(error);添加为回调的第一行。

的路要走:

虽然你可能会解决您的console.log(error),这个代码是注定,因为你,如果你收到一个错误不检查,并假设请求成功填补你看到的问题。网络连接是混乱的,并且请求可能由于很多原因而失败,因此在访问request.headers之前,您必须检查是否发生了任何错误并记录(或者将其显示给客户端,在X秒后重试请求,无论您喜欢最)。

提示:如果您有一个带错误参数的回调,请检查它。是否有作为第一个参数的原因。

的代码看起来就像这样:

request("https://www.fakeURL.com/", { 
    jar: true, 
    mode: 'no-cors' 
}, function(error, response, body) { 
    if (error) { 
     console.log(error); 
     makeTheRequestAgainIn(5000); // Milliseconds 
    } else { 
     doWhateverWith(response, body); 
    } 
}); 

错误:

只要你不能在浏览器中禁用CORS。您可以在节点中禁用它。js,因为它不是浏览器,这就是为什么在请求模块中有这个选项,但浏览器有一个安全措施是有原因的。如果他们可以避免,那么他们没有任何意义。

简而言之:是的,如果您没有在服务器中启用,您遇到了CORS问题。

普罗蒂普:当使用JavaScript在浏览器中处理,是一个很好的做法,开发工具开放(F12),因为你,这样,你已经看到了CORS错误在控制台自动登录(或任何网络错误发生)。另外,切换到网络选项卡并检查请求标题,响应等也是一个很好的做法。

编辑:刚注意到Chrome扩展的东西(党)。扩展是限制较少,因此是细做这些呼叫,你可以在这里阅读:https://developer.chrome.com/extensions/xhr

此外,检查request NPM模块source code,并没有no-cors值。我认为你混合了Request APIrequest模块。

+0

我试图做console.log(错误),它给了我这个: 错误:opts.mode的无效值(我会在上面的原始帖子中发布完整的东西,因为格式在评论中很奇怪)。 另外,根据您对CORS问题所说的话,这是否意味着如果我试图从我学校的成绩册网站上爬行/抓取,我将无法继续此项目?有没有什么可以完成我想要做的事情?再次感谢。 –

+0

@OmarBaradei是的,这意味着你不能在浏览器上禁用CORS。顺便说一下,刚刚注意到“Chrome Extesion”的事情。认为你正在做一个网站或什么的。扩展不像普通浏览那样有限,因为你可以在这里查看,所以你可以做你想做的,只要是一个扩展:https://developer.chrome.com/extensions/xhr简单地移除模式参数,在清单中设置权限并进行呼叫,但不要忘记遵循我的错误处理指导原则。错误检查是开发过程中要做的主要工作,并且您正在跳过它。 –

+0

@OmarBaradei此外,我检查了'request' npm模块,它没有'mode'参数的'no-cors'值。我想你混淆了互联网上的信息。如果你使用'request'模块(不同于Request API),你必须检查它的正确选项,在这里:https://github.com/request/request。如果您在源代码中检查了适当的行,您会发现没有“no-cors”选项:https://github.com/jhiesey/stream-http/blob/master/lib/request.js#L51 –