【问题标题】:Win32::IEAutomation will not click on links when IE >= 9Win32::IEAutomation 在 IE >= 9 时不会点击链接
【发布时间】:2014-05-16 09:02:31
【问题描述】:

在现代设置(Windows 7 64 位、IE 11、ActiveState Perl 5.16 64 位)上,Win32::IEAutomation (v0.5) 中的 Click 方法似乎不起作用。下面是一个示例,稍微改编自文档:

use Win32::IEAutomation;
my $ie = Win32::IEAutomation->new( visible => 1);
$ie->gotoURL('http://www.google.com');
$ie->getLink('linktext:', "About")->Click;       

此时,我应该在 IE 中看到“关于”页面。但是在IE中还是看到了谷歌的主页,无法使用Win32::IEAutomation中的Content方法获取“关于”页面的来源。

我在较旧的设置(Vista SP2 64 位、IE 9、ActiveState Perl 5.10.1)上遇到了同样的问题。但是当我对 IE8 而不是 IE9 使用类似的设置时,问题不会出现。因此,问题似乎在于 IE8 和后续 IE 版本之间的差异。

我可以做些什么来让示例脚本与最新版本的 IE 一起工作?

【问题讨论】:

  • @SinanÜnür - 谢谢。我将这些命令添加到序言中,但它们并没有改变任何东西。 (没有新的警告或错误。)我还尝试了使用旧软件设置的示例脚本,发现它有效——我已在帖子中添加了详细信息。

标签: perl web-scraping


【解决方案1】:

Win32::IEAutomationInternetExplorer.ApplicationMSHTML 公开的各种接口的薄包装。

因此,我尝试通过编写脚本来进行导航而不使用Win32::IEAutomation 来复制问题。在链接上使用click 方法不会启动导航,而将其href 传递给Navigate2 会启动导航。

click 方法“通过触发 HTMLFrameSiteEvents::onclick 事件来模拟点击”,这意味着将涉及页面上定义的任何 onClick 处理程序。我不确定为什么没有特别启动导航。

但是,问题并不特定于 Google 的主页:我尝试使用 example.com,在该页面上的链接上调用 click 方法也没有启动导航。

这是我用作测试平台的脚本:

#!/usr/bin/env perl

use strict;
use warnings;
use feature 'say';

use Win32::OLE qw(EVENTS in valof);
$Win32::OLE::Warn = 3;

my $url = 'https://www.google.com/';

my %event_handler = (
    DocumentComplete => \&onDocumentComplete,
);

my %page_handler = (
    'https://www.google.com/'
        => \&onPageGoogleHome,
    'https://www.google.com/intl/en/about/'
        => \&onPageGoogleAbout,
);

my $ie = Win32::OLE->new(
    "InternetExplorer.Application", sub { $_[0]->Quit }
);

Win32::OLE->WithEvents($ie, \&Event, 'DWebBrowserEvents2');

$ie->{Visible} = 1;
$ie->Navigate2($url);

Win32::OLE->MessageLoop;
Win32::OLE->SpinMessageLoop;

$ie->Quit;

sub Event {
    my ($ie, $event, @argv) = @_;

    if (exists $event_handler{$event}) {
        $event_handler{$event}->($ie, \@argv);
    }
    else {
        # unhandled event
    }
    return;
}

sub onDocumentComplete {
    my ($ie, $argv) = @_;
    my $url = valof($argv->[-1]);
    if (exists $page_handler{$url}) {
        $page_handler{$url}->($ie, $argv);
    }
    else {
        # unhandled page
    }
    return;
}

sub onPageGoogleHome {
    my ($ie, $argv) = @_;
    say "We are on Google's home page";
    my $links = $ie->Document->links;
    my $about_link;
    for my $link (in $links) {
        if ($link->innerText eq 'About') {
            say "Found 'About' link";
            $about_link = $link;
            last;
        }
    }
    if ($about_link) {
        # Doesn't work:
        # $about_link->click;

        $ie->Navigate2($about_link->href);
    }
    return;
}

sub onPageGoogleAbout {
    my ($ie, $argv) = @_;
    say "Yay, we are on the about page!";
    Win32::OLE->QuitMessageLoop;
    return;
}

版本信息:

这是为 MSWin32-x64-multi-thread 构建的 perl 5,版本 19,subversion 12 (v5.19.12)

Internet Explorer 11

Windows 8.1 专业版 64 位

【讨论】:

  • 非常感谢。我的最终目标是编写一个脚本来“点击”Javascript 链接(在充分使用 AJAX 的页面中),并下载随后出现在浏览器中的 HTML。我还没有找到任何类型的 Win32::OLE 教程可以准确地说明这个目标。但我认为我可能能够调整您的代码,以便它满足我的需要。我很快就会尝试。
【解决方案2】:

我在Strawberry Perl v5.18.2 和Win32::IEAutomation v0.5 以及 IE v11.0.9600.17105 中观察到与->Click() 相同的错误行为。

我的解决方法是直接使用gotoURL() 方法。这显然不适用于 javascript 操作,但适用于这个特定示例。

use strict;
use warnings;

use Win32::IEAutomation;

my $ie = Win32::IEAutomation->new( visible => 1);
$ie->gotoURL('http://www.google.com');

my $about = $ie->getLink('linktext:' => 'About')
    or die "Unable to find About";

# $about->Click(); # <--- does not work, using alternative method

$ie->gotoURL($about->linkUrl());

【讨论】:

  • 谢谢。我提供了 Google 示例,因为它非常简单,并且因为我希望解决它可以解决我更深层次的问题。您已经发现了更深层次的问题:我想使用 Win32::IEAutomation 来导航 Javascript 链接(在大量使用 AJAX 的页面上),但我不知道该怎么做。
  • 考虑使用 WWW::Mechanize::Firefox 进行 Javascript 页面自动化。我听说这方面取得了更大的成功。
猜你喜欢
  • 1970-01-01
  • 2018-02-18
  • 1970-01-01
  • 2011-04-04
  • 2015-09-06
  • 2012-02-26
  • 1970-01-01
  • 2014-02-25
  • 2012-12-17
相关资源
最近更新 更多