【问题标题】:How to get innertext from body of a URL如何从 URL 的正文中获取内部文本
【发布时间】:2018-01-19 18:30:13
【问题描述】:

我正在尝试在 nodejs 应用程序中获取 https://www.example.com/ 的内部文本。我尝试使用request npm 模块来获取 URL 的正文,如下所示:

function getBodyText() {
    request({
        url:'https://www.example.com/'
    }, (error, response, body) => {
        console.log(body.innerText);
    });
}

上面的代码显示了我所在的当前页面的正文(https:www.google.com)。我错过了什么吗?

【问题讨论】:

    标签: javascript html node.js httprequest


    【解决方案1】:

    在您上面的代码中,body 值只是一个字符串。另一方面,innerText 假设 body 是一个 DOM Node

    在 Node 中,DOM 不像在浏览器中那样存在,因此为了访问返回的 DOM 节点,您需要使用包 Cheerio 加载 body。您可以分配请求选项的transform 属性以使用cheerio.load() 将正文加载到DOM 中。然后就可以使用传统的DOM选择器遍历body了。

    为了在您的请求选项对象上使用the transform option,您需要从request 切换到request-promise。 (npm i --save request request-promise) 除了 request-promise 将使用 Bluebird 返回一个 A+ 承诺之外,它们的功能几乎相同,而 request 使用更传统的错误优先回调。

    由于 Cheerio 使用自己的 jQuery 实现,您可以参考他们的 docs 了解与返回的 DOM 交互时的差异。

    const cheerio = require('cheerio')
    const request = require('request-promise')
    
    request({
      method: 'GET',
      uri: 'https://google.com'
      transform: body => cheerio.load(body)
    })
    .then($ => {
      console.log($('p').text)
    })
    

    如果您不想切换到 request-promise,您仍然可以这样做并使用 Promises

    const cheerio = require('cheerio')
    const request = require('request')
    
    const getDOMFromURI = uri => {
      return new Promise((resolve, reject) => {
        request(uri, (err, res, body) => {
          if (err) {
            return reject(err)
          }
    
          return resolve(cheerio.load(body))
        })
       })
    }
    
    getDOMFromURI('https://google.com').then($ => {
      console.log($('p').text)
    })
    

    【讨论】:

      【解决方案2】:

      您必须使用其他一些技术组合。您似乎想废弃网站以获取数据。请使用 phantomjs 或 nightmare 或 puppeteer 或任何其他无头浏览器。

      一个小例子告诉你如何用 puppeteer 获得第一个结果标题

      const puppeteer = require('puppeteer');
      
      let scrape = async () => {
          const browser = await puppeteer.launch({headless: false});
          const page = await browser.newPage();
      
          await page.goto('https://www.google.com.pk/search?q=puppeteer');
          await page.waitFor(2000);
      
          const result = await page.evaluate(() => {
              let title = document.querySelector('h3').innerText;
      
              return {
                  title
              }
      
          });
      
          browser.close();
          return result;
      };
      
      scrape().then((value) => {
          console.log(value); // Success!
      });
      

      【讨论】:

        【解决方案3】:

        从文档中,如果使用 GET 方法,您可以使用字符串作为第一个参数:

        request('https://www.example.com', function (error, response, body) {
          console.log('error:', error); // Print the error if one occurred
          console.log('statusCode:', response && response.statusCode); // Print the 
          response status code if a response was received
          console.log('body:', body); // Print the HTML for the Google homepage.
          const dom = new JSDOM(body);
          console.log(dom.window.document.querySelector("p").textContent);
        });
        

        https://www.npmjs.com/package/request

        您可能还想尝试request-promise 模块或axios(这是用于发出 HTTP 请求的 1 号库)

        一旦你拿回了正文,你可能需要使用JSDOM 或其他一些库将正文转换为一个文档对象,然后你可以使用普通的 JS 方法甚至 jQuery / 另一个 DOM 遍历库进行遍历。

        【讨论】:

        • 我目前在http://www.google.com,但想获取https://www.example.com/ 的内容。我认为这在这种情况下行不通。
        • 对不起,我的 oopsie 更改了网址
        • 但是上面的代码仍然不会得到你所在的当前页面的正文而不是传入的请求url吗?
        • 我不明白你为什么说......当前页面......当前页面适用于浏览器,nodejs没有当前页面的概念......这段代码将在nodejs外面运行浏览器环境,并向 example.com 发出 GET 请求并返回它的内容
        猜你喜欢
        • 2016-10-14
        • 2021-07-30
        • 1970-01-01
        • 2020-10-09
        • 1970-01-01
        • 2020-01-09
        • 2014-09-17
        • 2012-08-07
        • 2013-06-01
        相关资源
        最近更新 更多