【问题标题】:How can I add a line break to each row in my returned table?如何在返回的表中为每一行添加换行符?
【发布时间】:2018-07-23 18:40:25
【问题描述】:

我正在开发一个网络抓取工具,并且成功打印了一个表格,但是表格的格式很糟糕。

我之前尝试过一些东西

1) const people = [...peopleList].map(personEntry => personEntry.innerText + '\n")

2) const people = [...peopleList].map(personEntry => personEntry.innerText).join("\n")

3)  .then(result => fs.writeFile('testfile.csv',JSON.stringify(result + "\n"),'utf8', function(err) {

我很困惑,我认为解决方案可能涉及一个循环并附加它,但我不是 100% 肯定的。

const Nightmare = require('nightmare')
const nightmare = Nightmare({ show: false  })
const fs = require('fs');


nightmare
  .goto('https://www.google.com/')
  .type('#lst-ib', 'datatables')
  .click('input[value= "Google Search"]')
  .click('.rc >.r > a')
  .select('select[name="example_length"]',"100")


  .evaluate(function() {
    const headerFields = document.querySelectorAll("#example thead tr th")
    const peopleList = document.querySelectorAll("#example tbody tr");
    const people = [...peopleList].map(personEntry => personEntry.innerText)
    const header = [...headerFields].map(headerEntry => headerEntry.innerText)

    return {
      log: header,
      list: people
    }
  })

  .end()

  .then(result => fs.writeFile('testfile.csv',JSON.stringify(result),'utf8', function(err) {
    if (err) {
      console.log('File not saved or corrupt');
    } else {
      console.log('your file is saved')
    }
  }))
  .catch(error =>{
    console.error('fail')
  })

*更新如果我在 CSV 预览器中打开文件,这就是我所看到的。我想要一行中的姓名、职位、办公室、年龄、开始日期、薪水,然后所有返回的人(以及他们的姓名办公室等)都返回他们自己的行。

有什么想法吗?

【问题讨论】:

  • 你能显示peopleList的样本值吗?
  • @JeremyLee 我现在添加了 csv 的样子,我将使用正则表达式来修复它的外观,但我很困惑为什么它不会将每个人添加到自己的行中)但是一个返回值当前可能是Name | Position | Office | Age | Start Date | Salary Airi Satou Accountant Tokyo 33 2008/11/18 60,000,它们应该在一个数组中,如下面的[airi,accountant,tokyo,33,2008/11/18,60000]
  • 所以它看起来像是一个制表符分隔值表。在这种情况下,您可以将\t 替换为,,然后将.join 全部替换为\n
  • 哦,我想我遇到了问题,因为它以前是一个节点列表,我使用扩展运算符来转换它 - 所以我应该映射节点列表!谢谢!
  • 啊,如果它返回的是节点列表而不是数组,那么您可能需要传播

标签: javascript node.js web-scraping fs nightmare


【解决方案1】:

此代码中发生了一些不正确的解析和字符串操作,但这是一个非常简单的修复:

const Nightmare = require('nightmare')
const nightmare = Nightmare({ show: true })
const fs = require('fs');


nightmare
  .goto('https://www.google.com')
  .type('#lst-ib', 'datatables')
  .click('input[value= "Google Search"]')
  .click('.rc >.r > a')
  .select('select[name="example_length"]', "100")

  .evaluate(function () {
    const headerFields = document.querySelectorAll("#example thead tr th")
    const peopleList = document.querySelectorAll("#example tbody tr")

    const people = Array
      .from(peopleList)
      .map(entry => entry
        .innerText
        .replace(/\t/g, ',')
      )
    const header = Array
      .from(headerFields)
      .map(headerEntry => headerEntry
        .innerText
      )
      .join(',')

    return ([])
      .concat(header, people)
      .join('\n')
  })

  .end()

  .then(result => fs.writeFile(
      './testfile.csv',
      result,
      'utf8',
      function (err) {
        if (err) throw err;
        console.log('your file is saved')
      }
    )
  )
  .catch((err) => {
    console.error(err)
  });

首先,我们将错误处理程序更改为更实际的示例,该示例每次都会将我们抛出到相同的 .catch 语句,并且可以接受调试器中断。

接下来我们将写入文件更改为写入原始字符串,这样它实际上会输出 CSV,而不是 JSON 字符串(这将导致所有内容都在同一行)

最后我们更改评估回调,将 nodeList(s) 转换为 Array,然后转换,最后用换行符将它们全部连接起来。

您可能遇到的唯一问题是时间问题,因此某些等待语句可能正是您想要的。

【讨论】:

  • 所以也许我应该从字面上告诉程序等待一定的时间等待响应以确保它是一致的?
  • 可能是的。页面导航真的很有帮助
  • 似乎执行超时解决了脚本不能 100% 工作的问题。默认它等待 30 秒,现在它更长了。 const nightmare = Nightmare({ show: false , executionTimeout: 100000})
【解决方案2】:

也许可以尝试一个模板文字,它似乎适用于这个短循环。在您的情况下,您可能想尝试:

const people = [...peopleList].map(personEntry => {`${personEntry.innerText} \n`})

示例循环:

for (var i=0; i<5; i++){
  console.log(`This is ${i} times through \n More Text On Next Line`) 
}

【讨论】:

    猜你喜欢
    • 2019-10-22
    • 2017-04-17
    • 2019-10-08
    • 2022-11-22
    • 2016-01-05
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多