当我使用 Nightmare 时,在页面之间移动并进行抓取

2023-12-15

有一个网站,其中包含一个包含 25 个条目列表的页面,其中每个条目都是指向包含我需要的一些信息的页面的链接。我想进入列表页面,然后: 1)点击第一个条目的链接 2)检索所有html 3)点击返回列表页面(有一个按钮) 4) 对所有其他列表重复此操作

我也想尽可能有效地做到这一点,我被告知这意味着利用承诺。这是我的代码草图,它不起作用:

var Nightmare = require('nightmare');
var nightmare = Nightmare({ openDevTools: true, show: true })
var Xray = require('x-ray');
var x = Xray();
var resultArr = [];

nightmare
.goto(hidTestURL)
.wait(2500)
.click('input[name="propertySearchOptions:advanced"]') //start navigating to listing page
.wait(2500)
.type('input[name="propertySearchOptions:streetName"]', 'Main')
.wait(2500)
.select('select[name="propertySearchOptions:recordsPerPage"]', '25')
.wait(2500)
.click('input[name="propertySearchOptions:search"]') //at listing page
.wait(2500)
.then(function(){
  nightmare
  .click('a[href^="Property.aspx?prop_id=228645"]') //first entry
  .evaluate(function(){ //retrieve info
    var resultArr = [];
    resultArr.push(document.querySelector('html').innerHTML);
  })
})

nightmare
.click('a[id="propertyHeading_searchResults"]') //return to listing page
.evaluate(function(){
  return resultArr.push(document.querySelector('html').innerHTML); retrieve listing page info to show that it returned.
})
.then(function (resultArr) {
  console.log('resultArr', resultArr);
  x(resultArr[1], 'body@html') //output listing page html
    .write('results.json');
})

这会到达列表页面,然后不再继续。我也尝试了相同的代码,但是return nightmare每次使用nightmare除了第一个。我见过一些使用的例子return,但是当我这样做时,代码抛出了错误。

我也尝试过不包括第三个nightmare(空格后面的那个),而是尝试直接进入旧的噩梦实例.click(),但这也引发了错误。

我显然需要一些关于噩梦的语法和语义的帮助,但除了 API 列表之外,网上没有太多文档。有谁知道我怎样才能做到这一点?


首先,像你拥有的那样调用Nightmare - 分成两条链 - 是probably不会做你想做的事。 (这个评论区是一个很好的入门读物,虽然很长。)内存服务,来自第二个链的操作将在第一个链之后立即排队,从而导致(可能)不良行为。你说你的写法略有不同 - 我很想看看它,听起来可能更接近一些。

其次,你试图举起resultArr in .evaluate(),这是不可能的。该函数传递给.evaluate()在 Electron 内部进行字符串化和重构 - 这意味着您将失去函数周围的环境上下文。这个例子 in nightmare-examples如果您好奇的话,可以更深入地了解一下。

第三,也许这是一个错字或我误解意图:你的href选择器使用开头为 (^=) 操作员,这是故意的吗?这是否应该是一个结尾($=)?

Fourth, 循环异步操作很棘手。我的印象是这也可能是一个绊脚石?

考虑到所有这些,让我们看看修改原始脚本。诚然未经测试,因为我无权访问你的测试 URL,所以这有点随意:

var Nightmare = require('nightmare');
var nightmare = Nightmare({ openDevTools: true, show: true })
var Xray = require('x-ray');
var x = Xray();

nightmare
.goto(hidTestURL)
.wait(2500)
.click('input[name="propertySearchOptions:advanced"]') //start navigating to listing page
.wait(2500)
.type('input[name="propertySearchOptions:streetName"]', 'Main')
.wait(2500)
.select('select[name="propertySearchOptions:recordsPerPage"]', '25')
.wait(2500)
.click('input[name="propertySearchOptions:search"]') //at listing page
.wait(2500)
.evaluate(function(){
  //using `Array.from` as the DOMList is not an array, but an array-like, sort of like `arguments`
  //planning on using `Array.map()` in a moment
  return Array.from(
    //give me all of the elements where the href contains 'Property.aspx'
    document.querySelectorAll('a[href*="Property.aspx"]'))
    //pull the target hrefs for those anchors
    .map(a => a.href);
})
.then(function(hrefs){
  //here, there are two options:
  //  1. you could navigate to each link, get the information you need, then navigate back, or
  //  2. you could navigate straight to each link and get the information you need.
  //I'm going to go with #1 as that's how it was in your original script.

  //here, we're going to use the vanilla JS way of executing a series of promises in a sequence.
  //for every href in hrefs,
  return hrefs.reduce(function(accumulator, href){
    //return the accumulated promise results, followed by...
    return accumulator.then(function(results){
      return nightmare
        //click on the href
        .click('a[href="'+href+'"]')
        //get the html
        .evaluate(function(){
          return document.querySelector('html').innerHTML;
        })
        //add the result to the results
        .then(function(html){
          results.push(html);
          return results;
        })
        .then(function(results){
          //click on the search result link to go back to the search result page
          return nightmare
            .click('a[id="propertyHeading_searchResults"]')
            .then(function() {
              //make sure the results are returned
              return results;
            });
        })
    });
  }, Promise.resolve([])) //kick off the reduce with a promise that resolves an empty array
})
.then(function (resultArr) {
  //if I haven't made a mistake above with the `Array.reduce`, `resultArr` should now contain all of your links' results
  console.log('resultArr', resultArr);
  x(resultArr[1], 'body@html') //output listing page html
    .write('results.json');
});

希望这足以让您开始。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当我使用 Nightmare 时,在页面之间移动并进行抓取 的相关文章

随机推荐

  • ColdFusion 9.0.0 TLSv1.2

    我正在运行 ColdFusion 9 0 Hotfix 3 我正在尝试让 TLSv1 2 适用于 cf http 标记 我首先升级到 Java 7 Update 80 然后升级到 Java 8 Update 25 使用 Wireshark
  • 具有多个模板参数错误的模板部分特化

    当我在具有一个模板参数的类上使用模板部分特化时 我可以特化这样的方法 include
  • C++ OpenGL:调用 gluPerspective 会引发未定义的引用错误? [复制]

    这个问题在这里已经有答案了 我正在使用 FreeGLUT 尝试使用 OpenGL 在 C 中创建我的第一个立方体 我有一个问题 每当我调用 gluPerspective 时 编译器都会抛出此错误 build Debug MinGW Wind
  • 有没有办法使用 C 标准库来测量微秒的时间?

    有没有平台无关使用 C 标准库测量微秒时间的方法 不幸的是 测量的精度取决于操作系统
  • 在经典 ASP / Javascript 中将对象插入全局范围

    这个问题与经典 ASP 中的 Javascript 有关 它与浏览器中运行的 Javascript 无关 设计为可重用的 JS 模块的典型构造如下 function globalScope declarations here this 这允
  • iframe 中的parent.location.reload 不工作 IE

    当我单击测试时 我需要刷新父站点 刷新浏览器 我有源index php 在 q php 中 a href testing a 它可以在 FF LAtest 版本 Chrome 中工作 但不能在 IE 9 中工作 他说 script70 权限
  • 向 hibernate JoinTable 添加附加属性

    我有两个实体 消息和用户 用户与消息具有多对多关系 一个用户可以拥有多条消息 并且消息 目前 为了使其不那么复杂 与用户具有多对多关系 一条消息可以发送给多个用户 我使用 JoinTable 连接两个实体 但是 我想在连接表中添加一个 状态
  • 如何获取小于/大于给定数字的最接近的浮点数

    这是一个示例函数 function step x min max return x gt min x lt max x 0 console log step 3 Number EPSILON 3 5 Expected 0 actual 3
  • 如何使用 Express 框架从 Node.js 中的请求中获取字段?

    我正在编写 Node js 脚本 但在集成 登录 表单时遇到问题 我可以使用静态 HTML 页面来完成此操作 但是使用动态 ejs 页面会导致问题 我的表单字段被报告为 未定义 var helmet require helmet var b
  • 如何解决 mtrand.RandomState.choice 中的内存错误?

    我正在尝试从 1e5 字符串中采样 1e7 项 但出现内存错误 从 1e4 个字符串中采样 1e6 个项目是很好的 我使用的是 4GB RAM 的 64 位机器 并且认为我不应该达到 1e7 的任何内存限制 有任何想法吗 python3 P
  • 消息系统数据库架构

    我正在尝试在 PHP 和 MySQL 中实现消息传递系统 但在决定如何处理表和查询时遇到一些困难 对于允许多个参与者的系统来说 最好的方法是什么 我想我可能需要 3 个表 除了用户表 就像是 Conversation id Messages
  • v8 存储一个字符串需要多少内存?

    我正在尝试计算 v8 中字符串的内存使用量 并且我知道单个字符将占用 2 个字节 但是当我在开发工具中检查浅层大小和保留大小时 我对结果感到困惑 function Student this name lll var a new Studen
  • jQuery,检查视频是否有高度/宽度

    我有一个
  • 如何将 FFMpeg 构建为 iOS 框架

    我正在尝试在 FFMpeg 上构建自己的播放器基础 我成功将 FFMpeg 构建为静态库 a 但需要复制另一个头文件才能使用 我希望它能像框架一样使用 但即使我将头文件添加到框架中 设置为公共 我的演示应用程序在 FFMpeg framew
  • ASP.NET:为什么无法禁用控件状态

    我知道 ASP NET 不允许禁用控件状态 有谁知道吗why 我用谷歌搜索了很多 但只看到这是不可能的 但找不到 为什么 任何对此的想法都将受到欢迎 附 在我的特定情况下 我需要将很多项目放入下拉列表中 这些项目不会用于服务器端事件 我需要
  • 我被刮伤了,我该如何防止这种情况发生?

    运行 IIS 7 每周几次 我会看到来自一个地理位置的 Google Analytics 上的大量点击 他们正在查看的网址序列显然是由某种算法生成的 所以我知道我正在被抓取内容 有什么办法可以防止这种情况发生吗 谷歌不只给我一个IP 这让我
  • Android 多列列表视图

    我正在为我的应用程序创建一个排行榜 高分列表 我想以 4 列显示数据 排名 名称 创建者 得分 并通过对象列表相应地填充它们 我想在列表中一次显示 5 个项目 总共 20 个项目 使列表可滚动 我找不到合适的方法来做到这一点 由于我的工作截
  • 填充内联元素的顶部和底部

    引用 Head First html 您可以在内联元素的顶部和底部添加内边距 但内边距不会影响其周围其他内联元素的间距 因此内边距会与其他内联元素重叠 a 据我理解上面的引用 向内联元素的顶部和底部添加填充不会 永远 对周围的元素产生任何影
  • 是否可以修复完整内存转储,以便不再需要运行 .imgscan /l ?

    由于某种原因 我已经开始接收来自需要运行的生产的转储 imgscan l first 现在 我倾向于使用从 powershell 脚本调用的 CDB 对转储运行小型查询 然而 运行 imgscan l每次都需要相当长的时间 是否可以以渲染的
  • 当我使用 Nightmare 时,在页面之间移动并进行抓取

    有一个网站 其中包含一个包含 25 个条目列表的页面 其中每个条目都是指向包含我需要的一些信息的页面的链接 我想进入列表页面 然后 1 点击第一个条目的链接 2 检索所有html 3 点击返回列表页面 有一个按钮 4 对所有其他列表重复此操