有趣的“getElementById()恰好取1个参数(给定2)”,有时它发生。有人可以解释一下吗? [英] Interesting "getElementById() takes exactly 1 argument (2 given)", sometimes it occurs. Can someone explain it?

查看:576
本文介绍了有趣的“getElementById()恰好取1个参数(给定2)”,有时它发生。有人可以解释一下吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#-*- coding:utf-8 -*-
import win32com.client, pythoncom
import time

ie = win32com.client.DispatchEx('InternetExplorer.Application.1')
ie.Visible = 1
ie.Navigate('http://ieeexplore.ieee.org/xpl/periodicals.jsp')
time.sleep( 5 )

ie.Document.getElementById("browse_keyword").value ="Computer"
ie.Document.getElementsByTagName("input")[24].click()







import win32com.client, pythoncom
import time

ie = win32com.client.DispatchEx('InternetExplorer.Application')
ie.Visible = 1
ie.Navigate('www.baidu.com')
time.sleep(5)

print 'browse_keword'
ie.Document.getElementById("kw").value ="Computer"
ie.Document.getElementById("su").click()
print 'Done!'

当运行第一部分代码时,它将弹出:

When run the first section code,it will popup:

ie.Document.getElementById("browse_keyword").value ="Computer"
TypeError: getElementById() takes exactly 1 argument (2 given)

第二部分代码运行ok。

And the second section code runs ok. What is the difference that making the result different?

推荐答案

作为 COMObject getElementById 如果网址是 http://ieeexplore.ieee.org/xpl/periodicals.jsp ,则几乎相当于

As a method of a COMObject, getElementById is built by win32com dynamically.
On my computer, if url is http://ieeexplore.ieee.org/xpl/periodicals.jsp, it will be almost equivalent to

def getElementById(self):
    return self._ApplyTypes_(3000795, 1, (12, 0), (), 'getElementById', None,)

如果网址是www.baidu.com将几乎等同于

If the url is www.baidu.com, it will be almost equivalent to

def getElementById(self, v=pythoncom.Missing):
    ret = self._oleobj_.InvokeTypes(1088, LCID, 1, (9, 0), ((8, 1),),v
            )
    if ret is not None:
        ret = Dispatch(ret, 'getElementById', {3050F1FF-98B5-11CF-BB82-00AA00BDCE0B})
    return ret

显然,如果你传递一个参数到第一个代码,你会收到一个 TypeError 。但是如果您尝试直接使用它,即调用 ie.Document.getElementById(),您将不会收到 TypeError ,但是 com_error

Obviously, if you pass an argument to the first code, you'll receive a TypeError. But if you try to use it directly, namely, invoke ie.Document.getElementById(), you won't receive a TypeError, but a com_error.

为什么 win32com 建立错误的代码?

让我们看看 ie ie.Document 。它们都是 COMObject s,更确切地说,是 win32com.client.CDispatch 实例。 CDispatch 只是一个包装类。核心是属性 _oleobj _ ,其类型为 PyIDispatch

Why win32com built the wrong code?
Let us look at ie and ie.Document. They are both COMObjects, more precisely, win32com.client.CDispatch instances. CDispatch is just a wrapper class. The core is attribute _oleobj_, whose type is PyIDispatch.

>>> ie, ie.Document
(<COMObject InternetExplorer.Application>, <COMObject <unknown>>)
>>> ie.__class__, ie.Document.__class__
(<class win32com.client.CDispatch at 0x02CD00A0>,
 <class win32com.client.CDispatch at 0x02CD00A0>)
>>> oleobj = ie.Document._oleobj_
>>> oleobj
<PyIDispatch at 0x02B37800 with obj at 0x003287D4>

建立 getElementById win32com 需要从 _oleobj _ 中获取 getElementById 方法的类型信息。大致上, win32com 使用以下过程

To build getElementById, win32com needs to get the type information for getElementById method from _oleobj_. Roughly, win32com uses the following procedure

typeinfo = oleobj.GetTypeInfo()
typecomp = typeinfo.GetTypeComp()
x, funcdesc = typecomp.Bind('getElementById', pythoncom.INVOKE_FUNC)
......

funcdesc 几乎包含所有导入信息,例如参数的数量和类型。
$ $ b如果网址是 http://ieeexplore.ieee.org /xpl/periodicals.jsp funcdesc.args (),而correc funcdesc.args 应为((8,1,None),)

funcdesc contains almost all import information, e.g. the number and types of the parameters.
If url is http://ieeexplore.ieee.org/xpl/periodicals.jsp, funcdesc.args is (), while the correc funcdesc.args should be ((8, 1, None),).

简言之, win32com 检索到错误的类型信息,因此它建立了错误的方法。

我不知道是怪的,PyWin32或IE。但是基于我的观察,我发现在PyWin32的代码没有什么错。另一方面,以下脚本在Windows脚本宿主中完美运行。

Long story in short, win32com had retrieved the wrong type information, thus it built the wrong method.
I am not sure who is to blame, PyWin32 or IE. But base on my observation, I found nothing wrong in PyWin32's code. On the other hand, the following script runs perfectly in Windows Script Host.

var ie = new ActiveXObject("InternetExplorer.Application");
ie.Visible = 1;
ie.Navigate("http://ieeexplore.ieee.org/xpl/periodicals.jsp");
WScript.sleep(5000);
ie.Document.getElementById("browse_keyword").value = "Computer";

Duncan已经指出IE的兼容模式可以防止问题。不幸的是,似乎无法从脚本启用兼容性模式。

但我发现了一个诀窍,可以帮助我们绕过问题。

Duncan has already pointed out IE's compatibility mode can prevent the problem. Unfortunately, it seems it's impossible to enable compatibility mode from a script.
But I found a trick, which can help us bypass the problem.

首先,您需要访问一个好的网站,它给我们一个HTML页面,并从中检索一个正确的文档对象。
p>

First, you need to visit a good site, which gives us a HTML page, and retrieve a correct Document object from it.

ie = win32com.client.DispatchEx('InternetExplorer.Application')
ie.Visible = 1
ie.Navigate('http://www.haskell.org/arrows')
time.sleep(5)
document = ie.Document

然后跳转到不起作用的页面

Then jump to the page which doesn't work

ie.Navigate('http://ieeexplore.ieee.org/xpl/periodicals.jsp')
time.sleep(5)

现在您可以通过旧的文档对象访问第二页的DOM。

Now you can access the DOM of the second page via the old Document object.

document.getElementById('browse_keyword').value = "Computer"


b $ b

如果使用新的 Document 对象,您将再次得到 TypeError

If you use the new Document object, you will get a TypeError again.

>>> ie.Document.getElementById('browse_keyword')
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
TypeError: getElementById() takes exactly 1 argument (2 given)

这篇关于有趣的“getElementById()恰好取1个参数(给定2)”,有时它发生。有人可以解释一下吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆