Selenium Perl句柄阴影DOM

dgsult0t  于 2022-11-15  发布在  Perl
关注(0)|答案(1)|浏览(140)

有很多使用Selenium Python处理shadow DOM的例子,我想在Perl中做同样的事情。
Perl的Selenium::Remote::Driver不支持shadow DOM,但我应该可以通过JavaScript来实现。
下面是我的Perl代码

#!/usr/bin/env perl

use Selenium::Chrome;

my $driver = Selenium::Chrome->new (
   startup_timeout => 60, 
   custom_args => "--log-path=/tmp/selenium_chromedriver",
   logfile => "/tmp/selenium_chromedriver2", 
   debug_on => 1,
   extra_capabilities => {
      'goog:chromeOptions' => {
         args => [
            '--no-sandbox',
            '--disable-dev-shm-usage', 
            '--window-size=1260,720',
            '--user-data-dir=/tmp/selenium_chrome',
         ],  
      },  
   },  
);

$driver->get("chrome-search://local-ntp/local-ntp.html"); # chrome new tab
my $shadow_host = $driver->find_element("html/body/ntp-app", "xpath");
my $shadow_root = $driver->execute_script('return arguments[0].shadowRoot', $shadow_host);

for my $e ( @{$shadow_root->find_elements(':host > *', 'css')} ) { 
   # error: Can't call method "find_elements" on unblessed reference
   print "found\n";
}

$driver->shutdown_binary();

但我得到了错误:无法在不受祝福的引用上调用方法“find_elements”。
如何克服此错误?
谢谢你的帮助。

  • 我的环境是:Ubuntu 18,Perl 5.26, selenium :铬1.46,铬99,铬驱动程序99。
  • 在Python 3.8.5中测试了相同的机制。
  • 为什么我不使用Python?因为我工作场所的服务器只有Perl,没有Python 3。
flvlnr44

flvlnr441#

下面的代码可以正常工作

#!/usr/bin/env perl

use Selenium::Chrome;

my $driver = Selenium::Chrome->new (
   startup_timeout => 60,
   custom_args => "--log-path=/tmp/selenium_chromedriver",
   logfile => "/tmp/selenium_chromedriver2",
   debug_on => 1,
   extra_capabilities => {
      'goog:chromeOptions' => {
         args => [
            '--no-sandbox',
            '--disable-dev-shm-usage',
            '--window-size=1260,720',
            '--user-data-dir=/tmp/selenium_chrome',
         ],
      },
   },
);

$driver->get("chrome-search://local-ntp/local-ntp.html"); # chrome new tab
my $shadow_host = $driver->find_element("html/body/ntp-app", "xpath");

package MyShadow {
   sub new {
      my ($class, %attrs) = @_;
      my $shadow_root = $attrs{driver}->execute_script('return arguments[0].shadowRoot', $attrs{shadow_host});
      return undef if ! $shadow_root;
      $attrs{shadow_root} = $shadow_root;
      bless \%attrs, $class;
   }
   sub find_element {
      my ($self, $target, $scheme) = @_;
      die "scheme=$scheme is not supported. Only css is supported" if $scheme ne 'css';
      return $self->{driver}->execute_script(
                 "return arguments[0].querySelector(arguments[1])",
                 $self->{shadow_root},
                 $target
             );
   }
   sub find_elements {
      my ($self, $target, $scheme) = @_;
      die "scheme=$scheme is not supported. Only css is supported" if $scheme ne 'css';
      return $self->{driver}->execute_script(
                "return arguments[0].querySelectorAll(arguments[1])",
                $self->{shadow_root},
                $target
      );
   }
};

my $shadow_driver = MyShadow->new(driver=>$driver, shadow_host=>$shadow_host);
if ($shadow_driver) {
   for my $e ( @{$shadow_driver->find_elements(':host > *', 'css')} ) {
      print "found\n";
   }
}

$driver->shutdown_binary();

要点:

  • 对于Selenium来说,无论是Python还是Perl,它们都是javascript的 Package 器,只要你得到正确的javascript,你就可以做任何你想做的事情。
  • 对于Shadow驱动程序,您需要实现的只是find_element()和find_elements()。
  • 我只实现了'css',没有'xpath',因为这是Python截至2022/09/19所做的。

相关问题