有趣的“getElementById()恰好取1个参数(给定2)”,有时它发生。有人可以解释一下吗? [英] Interesting "getElementById() takes exactly 1 argument (2 given)", sometimes it occurs. Can someone explain it?
问题描述
#-*- 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 COMObject
s, 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屋!