使用 dryscrape 进行网页抓取:选择单选按钮时出错 CSS

Web scraping with dryscrape: error selecting radio button CSS

我正在尝试从网页 (http://www.madrid.org/wpad_pub/run/j/MostrarFichaCentro.icm?cdCentro=28063799) 中使用 javascript 更新的 table 获取数据,我正在使用 dryscrape。我有一个代码可以很好地与页面加载时默认生成的 tables 配合使用。但我需要通过单击单选按钮(第二个 table 中标记为 "Primary" 的单选按钮)来更新其中一个。

我更改了我的代码,它看起来像这样:

from bs4 import BeautifulSoup
import pandas as pd
import dryscrape

render = dryscrape.Session()
render.visit("http://www.madrid.org/wpad_pub/run/j/MostrarFichaCentro.icm?cdCentro=28063799")
radiob = render.at_css('#nivEd12\.grafica3')
radiob.click()
source = render.body()
school_card = BeautifulSoup(source, "lxml")
school_tables = school_card.findAll('table', class_="tablaGraficaDatos")
table = list(school_tables)[1]
pd.read_html(table.prettify())

但我收到以下错误:

InvalidResponseError: {"class":"ClickFailed","message":"Failed to find position for element /html/body/div[@id='contenedor']/div[@id='solapas']/div[10]/table/tbody/tr[1]/td[1]/div[@id='solapaspanel1']/div[@id='cuerpoL']/div/div[@id='capaSelGrafica']/div[@id='display.grafica3']/table/tbody/tr[2]/td[2]/input[@id='nivEd12.grafica3'] because it is not visible"}

我也尝试过 xpath:

radiob = render.at_xpath('//*[(@id = "nivEd12.grafica3")]')

但是我得到了同样的错误。

我已经使用 Selector Gadget 获取 CSS 和 XPath。我想单选按钮的路径有一些错误,但我不知道如何修复它。有什么想法吗?

提前致谢。


更新

@CtheSky 给了我一个适用于单身 url 的解决方案。但是当我尝试循环到多个 url 时,我得到了一个错误。这是脚本。

schools_urls2 = ['http://www.madrid.org/wpad_pub/run/j/MostrarFichaCentro.icm?cdCentro=28077865',
 'http://www.madrid.org/wpad_pub/run/j/MostrarFichaCentro.icm?cdCentro=28063751',
 'http://www.madrid.org/wpad_pub/run/j/MostrarFichaCentro.icm?cdCentro=28004989',
 'http://www.madrid.org/wpad_pub/run/j/MostrarFichaCentro.icm?cdCentro=28004990']

school_tables_collection = {}
school_name_collection = []

render = dryscrape.Session()
for z, school in enumerate(schools_urls[:5]):
    render.visit(school)
    render.driver.exec_script('document.getElementById("nivEd12.grafica3").click();')
    source = render.body()
    school_card = BeautifulSoup(source, "lxml")
    school_tables = school_card.findAll('table', class_="tablaGraficaDatos")
    school_name = school_card.find(style="text-transform:uppercase").next.next
    for i, table in list(enumerate(school_tables)):
        if i <= 1:
            school_tables_collection[school_name + "_" + str(i)] = \
            pd.read_html(table.prettify())
            school_name_collection.append(school_name)
    print "Tables of school %s extracted" % schools_urls[z]

知道我做错了什么吗?


解决方案

我终于设法修复了它。这是我犯的一个愚蠢的错误:我调用的第一个 url 没有我正在寻找的按钮元素,所以它返回了错误。我在循环中包含了 tryexcept,现在可以使用了。

非常感谢@CtheSky 的帮助

正如错误信息所说,css选择没有问题。这是因为单选按钮是不可见的,所以点击失败。它的父节点未显示:

<div id="solapaspanel1" style="display: none;">...</div>

您可以 运行 一段 javascript 来触发该点击事件:

render.driver.exec_script('document.getElementById("nivEd12.grafica3").click();')

更新:

请注意,在您的第二个示例中,url http://www.madrid.org/wpad_pub/run/j/MostrarFichaCentro.icm?cdCentro=28077865 中没有包含 id=nivEd12.grafica3 的元素。因此,脚本通过在 Null 上调用 click() 方法而失败,这是不允许的并引发错误。

可能某些页面中没有目标对象,或者他们只是使用了另一个ID或名称。您应该使用更通用的规则来指定您想要的内容并避免此错误,您可以通过 school_card.find_XX(...) 检查元素是否存在或使用 eval_script 到 运行 一个 javascript 语句如果你喜欢。