Selenium Perl处理影子DOM



有很多使用Selenium Python处理shadow DOM的例子。我想在Perl中也这样做。

Perl的Selenium::Remote::Driver不支持shadowDOM,但我应该能够通过JavaScript实现。我的灵感来自使用selenium访问shadow-dom树。

以下是我在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 "foundn";
}
$driver->shutdown_binary();

但我得到了一个错误:不能调用方法"find_elements";未经处理的参考。

我该如何克服这个错误?

谢谢你的帮助。

  • 我的环境是:ubuntu 18,Perl 5.26,Selenium:Chrome1.46,Chrome99、镀铬器99
  • 使用Python测试了相同的机制3.8.5
  • 为什么我不使用Python?因为我工作的地方的服务器只有Perl,没有Python 3

以下代码适用于

#!/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 "foundn";
}
}
$driver->shutdown_binary();

要点:

  • 对于Selenium,无论是Python还是Perl,它们都是javascript。只要你得到正确的javascript,你就可以不管你想要什么。

  • 对于Shadow驱动程序,您只需要实现find_element((和find_elements((。

  • 我只实现了"css",没有实现"xpath",因为截至2022/09/19,Python就是这么做的。

最新更新