9

我想知道 Mojo::UserAgent 是否可以做类似下面的事情:

假设我有以下代码:

my $ua  = Mojo::UserAgent->new;
my $res = $ua->get('mojolicious.org/perldoc')->result;

是否可以拦截 Mojo::UserAgent 请求并将其发送到其他知道 javascript 的 Web 客户端,其结果以 Mojo::Transaction::HTTP ($res above ) 形式返回,用户可以继续使用 Mojo::UserAgent界面结果。

即我想要以下内容:

Mojo::UserAgent-> HTTP 请求 -> 拦截 HTTP 请求 -> 将 HTTP 请求发送到支持 javascript 的 Web 客户端,例如 WWW::Chrome::Mechanize 或 FireFox::Marionette -> JavaScript Web 客户端执行请求 ->返回结果被截取并更改为 Mojo::Transaction::HTTP

或者

Mojo::UserAgent -> 非阻塞 HTTP 请求 -> 非阻塞 HTTP 响应 -> 发送到像 webkit 这样的嵌入式 Web 浏览器 -> 得到 Mojo::Transaction::HTTP 的结果

任何想法/示例如何让 Mojo::UserAgent 使用 javascript?

4

2 回答 2

5

这几乎总是可能的,但实际的问题是您要完成的工作量。这个特定答案的一部分是您希望如何拦截请求。这很简单,因为您可以包装该start方法(如Mojo::UserAgent::Role::Queued所做的那样)。

拦截请求后,随心所欲。获取原始响应并让 Mojo 解析它并构建事务的那一部分。之后,您重新进入正常进程。

有一段时间人们会推荐无头浏览器phantomjs,但看起来该项目已经停滞不前。有 Joel Berger 的Mojo::Phantom,但这并不是你想要的。

最后,请记住,几乎每个人都希望它存在,但事实并非如此。那是那里的重要信息。;)

如果您仍然想解决这个问题,那么在此过程中提出范围更窄的问题可能会有所帮助。

祝你好运!

于 2018-09-11T18:01:24.733 回答
1

不完全是你问的,但可能足够接近可以通过以下方式实现:

  • 安装无头镀铬
  • 设置 nodejs + 几个模块
  • 使用客户端事件 outerHTML 获取加载和解析
  • 从 perl 代码中读取 outerHTML

如下:

# just a perl oneliner, parsing the scrapped html and passing it to Mojo::DOM
perl -MMojo::DOM -e '$s=`node scrap-html.js`; for my $e (Mojo::DOM->new($s)->find("html body a.scroll")->each){ print $e->text}';

scrap-html.js 的代码在哪里

  // file: scrap-html.js src: https://gist.github.com/magician11/a979906401591440bd6140bd14260578
  const CDP = require('chrome-remote-interface');
  const chromeLauncher = require('chrome-launcher');

  (async function() {
    const launchChrome = () =>
      chromeLauncher.launch({ chromeFlags: ['--disable-gpu', '--headless','--blink-settings=imagesEnabled=false'] });

    const chrome = await launchChrome();
    const protocol = await CDP({ port: chrome.port });
    const timeout = ms => new Promise(resolve => setTimeout(resolve, ms));

    // See API docs: https://chromedevtools.github.io/devtools-protocol/
    const { Page, Runtime, DOM } = protocol;
    await Promise.all([Page.enable(), Runtime.enable(), DOM.enable()]);

    uri = 'https://qto.fi/qto/view/readme_doc'
    Page.navigate({ url: uri });

    // wait until the page says it's loaded...
    Page.loadEventFired(async () => {
      try {
        await timeout(4000); // give the JS some time to load

        // get the page source
        const rootNode = await DOM.getDocument({ depth: -1 });
        const pageSource = await DOM.getOuterHTML({
          nodeId: rootNode.root.nodeId
        });
        protocol.close();
        chrome.kill();
        console.log ( pageSource.outerHTML)
      } catch (err) {
        console.log(err);
      }
    });
  })();
  //eof file: scrap-html.js

ubuntu 上的整个设置示例:

  # start install chromium-headless
  sudo apt-get update
  sudo apt-get install -y software-properties-common
  sudo apt-get install -y chromium-browser
  sudo apt-get update

  wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
  sudo dpkg -i google-chrome-stable_current_amd64.deb
  apt --fix-broken install
  # stop install chromium-headless
  # start installing the nodejs + node modules
  sudo apt install nodejs
  sudo npm install -g chrome-remote-interface
  sudo npm install -g chrome-launcher
  export NODE_PATH=/usr/local/lib/node_modules
  # stop installing the nodejs + modules
于 2019-12-01T14:13:05.603 回答