首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在GeckoFx中使用GeckoFx与C#?

在GeckoFx中使用GeckoFx与C#?
EN

Stack Overflow用户
提问于 2017-02-06 02:31:39
回答 1查看 645关注 0票数 3

我正在使用GeckoFx执行登录到一个特定的网站。如果登录失败(或需要其他身份验证,如ReCaptcha),该网站将使用新信息编辑页面。不幸的是,当页面被更新时,我能够访问一个事件是至关重要的。我主要尝试了很多方法

  • 每次尝试登录时,持续检查uri是否仍然相同,并对所讨论的特定元素进行后续检查(查看是否更改了display: none属性。(这导致了无限循环,因为GeckoFx似乎以非阻塞的方式更新页面,导致程序进入无限循环)
  • 在登录请求和使用上述uri检查之间休眠约5秒。所有这一切(可以预见,我正在抓取吸管)只是将浏览器冻结了5秒,但仍然无法更新页面。
  • 当页面被更新时,搜索GeckoFx代码基以寻找类似于DocumentCompleted事件的特定事件(没有这样的运气)。

我读过的最常见的方法(也是最有意义的方法)是使用MutationObserver。似乎整个互联网上的所有答案都涉及到注入Javascript以完成所需的任务。由于我所有的编程背景都没有涉及到web开发,所以我试图坚持我所知道的。

这是我到目前为止的做法,不幸的是,它不是很多。

代码语言:javascript
复制
public class GeckoTestWebLogin
{
    private readonly string _user;
    private readonly string _pass;
    public GeckoWebBrowser Gweb;
    public Uri LoginUri { get; } = new Uri("https://website.com/login/");

    public bool LoginCompleted { get; private set; } = false;
    public bool Loaded { get; private set; } = false;

    public GeckoTestWebLogin(string user, string pass)
    {
        _user = user;
        _pass = pass;
        Xpcom.EnableProfileMonitoring = false;
        Xpcom.Initialize("Firefox");

        //this code is for testing purposes, it will be removed upon project completion
        CookieManager.RemoveAll();

        Gweb = new GeckoWebBrowser();
        Gweb.DocumentCompleted += DocLoaded;

        //right about here is where I get lost, where can I set a callback method for the observer to report back to? Is this even how it works?
        MutationObserver mutationObserver = new MutationObserver(Gweb.Window.DomWindow, (nsISupports)Gweb.Document.DomObject);
    }

    private void TestObservedEvent(string parms, object[] objs)
    {
        MessageBox.Show("The page was changed @ " + DateTime.Now);
    }

    public void DocLoaded(object obj, GeckoDocumentCompletedEventArgs e)
    {
        Loaded = true;
        if (Gweb.Url != LoginUri) return;
        AttemptLogin();
    }

    private void AttemptLogin()
    {
        GeckoElementCollection elements = Gweb.Document.GetElementsByTagName("input");
        foreach (GeckoHtmlElement element in elements)
        {
            switch (element.Id)
            {
                case "username":
                    element.SetAttribute("value", _user);
                    break;
                case "password":
                    element.SetAttribute("value", _pass);
                    break;
                case "importantchangedinfo":
                    GeckoHtmlElement authcodeModal =
                        (GeckoHtmlElement)
                            Gweb.Document.GetElementsByClassName("login_modal").First();
                    if (authcodeModal.Attributes["style"].NodeValue != "display: none")
                    {
                        InputForm form = new InputForm { InputDescription = "Captcha Required!" };
                        form.ShowDialog();
                        elements.FirstOrDefault(x => x.Id == "captchabox")?.SetAttribute("value", form.Input);
                    }
                    break;
            }
        }
        elements.FirstOrDefault(x => x.Id == "Login")?.Click();
    }

    public void Login()
    {
        //this will cause the DocLoaded event to fire after completion
        Gweb.Navigate(LoginUri.ToString());
    }
}

正如上述代码在注释中所述,我完全迷失在

代码语言:javascript
复制
MutationObserver mutationObserver = new MutationObserver(Gweb.Window.DomWindow, (nsISupports)Gweb.Document.DomObject);

GeckoFxMutationObserver源代码中,我似乎找不到任何东西可以让我设置回调/事件/whathaveyou。我的方法是正确的吗?还是除了将Javascript注入页面之外,我别无选择?

非常感谢,谢谢。

下面是我对Tom回答中的选项2的尝试:

(加入GeckoTestWebLogin)

代码语言:javascript
复制
    public void DocLoaded(object obj, GeckoDocumentCompletedEventArgs e)
    {
        Loaded = true;
        if (Gweb.Url != LoginUri) return;

        MutationEventListener mutationListener = new MutationEventListener();
        mutationListener.OnDomMutation += TestObservedEvent;
        nsIDOMEventTarget target = Xpcom.QueryInterface<nsIDOMEventTarget>(/*Lost here*/);
        using (nsAString modified = new nsAString("DOMSubtreeModified"))
            target.AddEventListener(modified, mutationListener, true, false, 0);

        AttemptLogin();
    }

MutationEventListener.cs:

代码语言:javascript
复制
public delegate void OnDomMutation(/*DomMutationArgs args*/);

public class MutationEventListener : nsIDOMEventListener
{
    public event OnDomMutation OnDomMutation;

    public void HandleEvent(nsIDOMEvent domEvent)
    {
        OnDomMutation?.Invoke(/*new DomMutationArgs(domEvent, this)*/);
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-02-07 03:18:00

我认为Geckofx的webidl编译器目前还不够先进,无法生成回调构造函数。

选项1. -增强MutationObserver源代码。

您可以手动修改MutationObserver源代码以添加必要的构造函数回调。然后重新编译Geckofx。(我还没看清楚这有多难)

选项2。-使用旧风格的变异事件。

代码语言:javascript
复制
public class DOMSubtreeModifiedEventListener : nsIDOMEventListener
{
     ... // Implement HandleEvent 
}

然后类似于(可能在DocumentCompleted事件处理程序中):

代码语言:javascript
复制
    _domSubtreeModifiedEventListener = new DOMSubtreeModifiedEventListener(this);

    var target = Xpcom.QueryInterface<nsIDOMEventTarget>(body);
    using (nsAString subtreeModified = new nsAString("DOMSubtreeModified"))
        target.AddEventListener(subtreeModified, _domSubtreeModifiedEventListener, true, false, 0);

选项3. -使用Idle + Check。

添加winforms Application.idle事件处理程序-并检查文档,以了解其何时准备就绪。

选项4. -注入javascript回调。

(正如您已经提到的那样)--这个示例正在等待到调整大小之后。

基本上注入:"<body onresize=fireResizedEventAfterDelay()>":然后注入如下内容:

代码语言:javascript
复制
 string fireResizedEventAfterDelayScript = "<script>\n" +
            "var resizeListner;" +
            "var msDelay = 20;" +
            "function fireResizedEventAfterDelay() {" +
            "clearTimeout(resizeListner);" +
            "resizeListner = setTimeout(function() { document.dispatchEvent (new MessageEvent('resized')); }, msDelay);" +
            "}\n" +
            "</script>\n";

然后在C#中:

代码语言:javascript
复制
browser.AddMessageEventListener("resized", (s) => runafterImDone())
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42059605

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档