执行this HTML page的以下代码时出现错误,但此错误仅发生在/html/body/div[3]/div[1]/div[1]/div[1]/div/div[10]/a/div[1]/div[2]
:
WebDriverException:消息:{“errorMessage”:“null不是对象 (近 '... ULL).singleNodeValue.click(); ...')”, “请求”:{ “报头”:{ “接受”: “应用/ JSON”, “接受编码”: “同一性”, “连接”: “关闭”, “内容长度”: “223”, “内容类型”: “应用/ JSON;字符集= UTF-8”, “主机”:“127.0.0.1:34955","User - 代理“:”巨蟒 HTTP AUTH “},” httpVersion “:” 1.1" , “方法”: “POST”, “后”: “{\” 的sessionId \“: \“ddd5e2d0-10e4-11e8-8645-3d3d785f60f2 \”,\“args \”:[],\“script \”: \“window.document.evaluate('/ HTML /体/格[3] / DIV 1 /格1 /格1 / DIV / DIV [10] /一个/格1 / DIV [2]”, document,null,9, 空).singleNodeValue.click(); \ “}”, “URL”: “/执行”, “urlParsed”:{ “锚”: “”, “查询”: “”, “文件”: “执行”, “目录”: “/”, “路径”: “/执行”, “相对的”: “/执行”, “端口”: “”, “宿主”: “”, “密码”: “”, “用户” : “”, “用户信息”: “”, “权威”: “”, “协议”: “”, “源”: “/执行”, “queryKey”:{}, “块”:[ “执行”] }, “urlOriginal”: “/会话/ ddd5e2d0-10e4-11e8-8645-3d3d785f60f2 /执行”}} 屏幕截图:可通过屏幕获取
这是代码:
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)
答案 0 :(得分:1)
您使用一个查询进行计数,另一个进行迭代,产生不同的结果。解决这个问题的天真方法是使用相同的查询来计算和迭代。
哪个查询?这取决于你想要什么,因为你的查询选择了不同的东西(因此你会看到的错误):
.w-dyn-item
个元素;但这些元素分布在三个.w-dyn-list
容器中 - 一个用于.gold
,一个用于.silver
,一个用于.bronze
- 并且,就目前而言,.w-dyn-item
个元素 - .gold
。如果您只想要.gold
项,则必须调整您的点数查询:
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#click()
:
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()
这样做更好,但XPath查询仍然非常具体且不灵活;如果列表项中DOM树的排列发生任何变化,您的查询将会中断。此外,XPath查询也没有告诉我您尝试点击的内容,因此无法告诉为什么您正在尝试点击它。
相反,由于您不再向浏览器发送XPath,您可以使用其他CSS查询以更灵活的方式更好地表达自己:
items = driver.find_elements_by_class_name("w-dyn-item")
for item in items:
item.find_element_by_class_name("description").click()
# ...
现在很清楚,您正在尝试点击每个项目的说明。而且,由于您未指定 ,因此该网站可以更改(在合理范围内)而不会破坏您的脚本。
通过仔细查看脚本,可以看出您点击项目描述的唯一原因是您可以导航到详细信息页面以提取项目标题。但该信息已存在于初始列表中:每个项目的<h4>
元素。
除非您需要的其他信息不在列表页面上,否则您无需导航到详细信息页面。相反,只需找到<h4>
元素并提取其文本:
item_headings = driver.find_elements_by_css_selector(".w-dyn-item h4")
project_titles = [item_heading.text for item_heading in item_headings]
答案 1 :(得分:0)
您可以在页面的HTML中看到只有10个带有xpath的div元素
w-dyn-item
虽然有<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="vertical"
android:layout_weight="1">
<TextView
android:id="@+id/TextViewGameName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="FirstTextView"
android:textColor="@android:color/holo_red_dark"/>
<TextView
android:id="@+id/TextViewPrices"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SecondTextView"
android:textColor="@android:color/holo_blue_dark"/>
</LinearLayout>
<Button
android:id="@+id/ButtonRemove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="usuń"
android:layout_weight="0">
</Button>
类有73个元素(没有元素只有 这个类)。
结果是您尝试迭代10个数组中的73个元素。