WebDriverException:消息:{" errorMessage":" null不是一个对象 [英] WebDriverException: Message: {"errorMessage":"null is not an object

查看:198
本文介绍了WebDriverException:消息:{" errorMessage":" null不是一个对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

执行以下此HTML页面的代码时出现错误,但此错误只发生在 / html / body / div [3] / div [1] / div [1] / div [1] / div / div [10] / a / div [1] / div [2]


WebDriverException:消息:{errorMessage:null不是对象
接近
'... ull).singleNodeValue.click(); ...'),request:{headers:{Accept:application / json,Accept-Encoding : 同一性, 连接: 关闭, 内容长度: 223, 内容类型: 应用/ JSON;字符集= UTF-8, 主机:127.0.0.1: 34955,User-Agent:Python
http
auth},httpVersion:1.1,method:POST,post:{\sessionId \:
\ddd5e2d0-10e4-11e8-8645-3d3d785f60f2\,\args \:[],\script \:
\ window.document.evaluate('/ html / body / div [3] / div 1 / div < a href = https://topicolist.com/ongoing-icorel =nofollow noreferrer> 1 / div 1 / div / div [10] / a / div 1 / div [2] ',
document,null,9,
null).singleNodeValue.click(); \},url:/ execute,urlParsed:{anchor: , 查询: , 文件: 执行, 目录: /, 路径: /运行, 相对: /运行, 口: , 宿主: , 密码: , 用户: , 用户信息: , 权威: , 协议: , 源: /执行 ,queryKey:{},chunks:[execute]},urlOriginal:/ session / ddd5e2d0-10e4-11e8-8645-3d3d785f60f2 / execute}}
屏幕截图:


这是代码:

  driver = webdriver.PhantomJS()
driver.implicitly_wait(20)
driver.set_window_size(1120,550)
driver.get(https://topicolist.com/ongoing- ico)

num_options = len(driver.find_elements_by_cl我在范围(num_options)中为

xpath =/ html / body / div [3] / div [1] / div [1] / div [1] / div / div [+ str(i + 1)+] / a / div [1] / div [2]
print xpath
execute_script(driver,xpath)

project_title = driver.find_elements_by_class_name(heading-49)[0] .text.strip()
print project_title

time.sleep(10)
driver.back()

driver.quit()


def execute_script(driver,xpath):
execute_string =window.document .evaluate('{}',document,null,9,null).singleNodeValue.click();。format(xpath)

return driver.execute_script(execute_string)


解决方案

天真的解决方案



您使用一个查询进行计数,另一个查询进行迭代,产生不同的结果。解决这个问题的简单方法是使用相同的查询进行计数和迭代。



哪个查询?这取决于你想要什么,因为你的查询选择不同的东西(因此你看到的错误):


  1. 您的CSS查询获取所有 .w-dyn-item 元素;但是这些元素分布在三个 .w-dyn-list 容器 - 一个用于 .gold ,一个用于 .silver ,另一个用于 .bronze - 并且,按照现状,
  2. 您的XPath查询仅从第一个容器中获取 .w-dyn-item 元素 - .gold

如果您只想要 .gold 项目,您必须调整您的计数查询:


$ b

  num_options = len(driver.find_elements_by_css_selector(。w-dyn-list.gold。 w-dyn-item))
#...

如果你想要所有这些项目,你必须调整你的迭代查询:

for i in range(num_options ):
xpath =/ html / body / div [3] / div [1] / div [1] / div / div / div [+ str(i + 1)+] / a / div [1] / div [2]
#...



更好的解决方案



但你确实如此只需点击一个元素即可完成大量工作。你不需要使用JavaScript; Selenium提供 WebElement#点击() 就可以达到这个目的:

  items = driver.find_elements_by_class_name(w-dyn-item)
用于item中的项目:
item.find_element_by_xpath(./ a / div / [1] / div [2])。click ()

这样更好,但XPath查询仍然非常具体且不灵活;如果关于列表项目中DOM树排列的任何变化,您的查询将会中断。此外,XPath查询也不会告诉我您要点击的是什么,因此无法告诉您为什么要单击它。

>

相反,由于您不再向浏览器发送XPath,因此您可以使用另一个CSS查询以更灵活的方式更好地表达自己:

items = driver.find_elements_by_class_name(w-dyn-item)
用于商品中的物品:
item.find_element_by_class_name(description)。click()
#...

现在很明显,您正试图点击每个项目的说明。而且由于您没有指定 描述的出现位置,所以网站可以在合理范围内进行更改,而不会中断您的脚本。

最佳解决方案



通过仔细查看脚本,可以看到您点击项目描述的唯一原因是您可以导航到详细信息页面提取项目标题。但是,这些信息已经存在于初始列表中:每个项目的< h4> 元素。

除非您需要的附加信息不在列表页面上,否则您无需导航至详细信息页面。取而代之的是,找到< h4> 元素并提取它们的文本: $ b

 project_titles = [item_heading.text for item_heading in item_headings] 
item_headings = driver.find_elements_by_css_selector(。w-dyn-item h4) >


I get the error when executing the following code for this HTML page, but this error only happens at /html/body/div[3]/div[1]/div[1]/div[1]/div/div[10]/a/div[1]/div[2]:

WebDriverException: Message: {"errorMessage":"null is not an object (near '...ull).singleNodeValue.click();...')","request":{"headers":{"Accept":"application/json","Accept-Encoding":"identity","Connection":"close","Content-Length":"223","Content-Type":"application/json;charset=UTF-8","Host":"127.0.0.1:34955","User-Agent":"Python http auth"},"httpVersion":"1.1","method":"POST","post":"{\"sessionId\": \"ddd5e2d0-10e4-11e8-8645-3d3d785f60f2\", \"args\": [], \"script\": \"window.document.evaluate('/html/body/div[3]/div1/div1/div1/div/div[10]/a/div1/div[2]', document, null, 9, null).singleNodeValue.click();\"}","url":"/execute","urlParsed":{"anchor":"","query":"","file":"execute","directory":"/","path":"/execute","relative":"/execute","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/execute","queryKey":{},"chunks":["execute"]},"urlOriginal":"/session/ddd5e2d0-10e4-11e8-8645-3d3d785f60f2/execute"}} Screenshot: available via screen

This is the code:

driver = webdriver.PhantomJS()
driver.implicitly_wait(20)
driver.set_window_size(1120, 550)
driver.get("https://topicolist.com/ongoing-ico")

num_options = len(driver.find_elements_by_class_name("w-dyn-item"))
for i in range(num_options):
    xpath = "/html/body/div[3]/div[1]/div[1]/div[1]/div/div[" + str(i+1) + "]/a/div[1]/div[2]"
    print xpath
    execute_script(driver, xpath)

    project_title = driver.find_elements_by_class_name("heading-49")[0].text.strip()
    print project_title

    time.sleep(10)
    driver.back()

driver.quit()


def execute_script(driver, xpath):
    execute_string = "window.document.evaluate('{}', document, null, 9, null).singleNodeValue.click();".format(xpath)

    return driver.execute_script(execute_string)

解决方案

A naive solution

You're using one query to count and another to iterate, producing different results. The naive way to solve this is to use the same query to count and iterate.

Which query? That depends on what you want, since your queries select different things (hence the error you're seeing):

  1. your CSS query fetches all .w-dyn-item elements; but those elements are spread across three .w-dyn-list containers—one for .gold, one for .silver, and one for .bronze—and, as it stands,
  2. your XPath query only fetches .w-dyn-item elements from the first container—.gold.

If you want only the .gold items, you'll have to adjust your count query:

num_options = len(driver.find_elements_by_css_selector(".w-dyn-list.gold .w-dyn-item"))
# ...

If you want all of the items, you'll have to adjust your iteration query:

for i in range(num_options):
    xpath = "/html/body/div[3]/div[1]/div[1]/div/div/div[" + str(i+1) + "]/a/div[1]/div[2]"
    # ...

A better solution

But you're doing a lot of work just to click an element. You don't need to use JavaScript; Selenium provides WebElement#click() for just this purpose:

items = driver.find_elements_by_class_name("w-dyn-item")
for item in items:
    item.find_element_by_xpath("./a/div/[1]/div[2]").click()

This is better, but the XPath query is still very specific and inflexible; if anything about the arrangement of the DOM tree in the list item changes, your query will break. Also, the XPath query also doesn't tell me what you're trying to click, making it impossible to tell why you're trying to click it.

Instead, since you're no longer sending XPath to the browser, you can use another CSS query to better express yourself in a more resilient way:

items = driver.find_elements_by_class_name("w-dyn-item")
for item in items:
    item.find_element_by_class_name("description").click()
    # ...

Now it's clear that you're trying to click on the description for each item. And because you're not specifying where the description appears, the site can change (within reason) without breaking your script.

The best solution

And by looking even closer at your script, one can see that the only reason you're clicking on the item description is so that you can navigate to the detail page to extract the project title. But that information is already present in the initial list: in the <h4> element for each item.

Unless there's additional information you need that doesn't exist on the list page, you don't need to navigate to the detail page. Instead, just find the <h4> elements and extract their text:

item_headings = driver.find_elements_by_css_selector(".w-dyn-item h4")
project_titles = [item_heading.text for item_heading in item_headings]

这篇关于WebDriverException:消息:{&quot; errorMessage&quot;:&quot; null不是一个对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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