使用机械化和Python,在点击href="javascript:void(0);"链接后获取响应

7
我需要从一个填写表格的页面中抓取一些数据(我已经用机械臂完成了这个过程)。问题在于,该页面返回许多页面的数据,而我无法获取这些页面的数据。
从第一个结果页面中获取数据没有问题,因为它已经在搜索后显示 - 我只需提交表单并获取响应即可。
我分析了结果页面的源代码,似乎它使用了Java Script、RichFaces(JSF的某个带有ajax的库,但我可能错了,因为我不是网页专家)。
然而,我成功地找到了如何进入其余的结果页面。我需要点击以下形式的链接(href="javascript:void(0);",完整代码如下):
<td class="pageNumber"><span class="rf-ds " id="SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233"><span class="rf-ds-nmb-btn rf-ds-act " id="SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_1">1</span><a class="rf-ds-nmb-btn " href="javascript:void(0);" id="SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_2">2</a><a class="rf-ds-nmb-btn " href="javascript:void(0);" id="SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_3">3</a><a class="rf-ds-nmb-btn " href="javascript:void(0);" id="SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_4">4</a><a class="rf-ds-nmb-btn " href="javascript:void(0);" id="SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_5">5</a><a class="rf-ds-nmb-btn " href="javascript:void(0);" id="SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_6">6</a><a class="rf-ds-nmb-btn " href="javascript:void(0);" id="SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_7">7</a><a class="rf-ds-nmb-btn " href="javascript:void(0);" id="SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_8">8</a><a class="rf-ds-nmb-btn " href="javascript:void(0);" id="SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_9">9</a><a class="rf-ds-nmb-btn " href="javascript:void(0);" id="SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_10">10</a><a class="rf-ds-btn rf-ds-btn-next" href="javascript:void(0);" id="SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_next">»</a><a class="rf-ds-btn rf-ds-btn-last" href="javascript:void(0);" id="SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_l">»»»»</a>

<script type="text/javascript">new RichFaces.ui.DataScroller("SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233",function(event,element,data){RichFaces.ajax("SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233",event,{"parameters":{"SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233:page":data.page} ,"incId":"1"} )},{"digitals":{"SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_9":"9","SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_8":"8","SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_7":"7","SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_6":"6","SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_5":"5","SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_4":"4","SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_3":"3","SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_1":"1","SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_10":"10","SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_2":"2"} ,"buttons":{"right":{"SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_next":"next","SomeSimpleForm:SomeSimpleTable:j_idt211:j_idt233_ds_l":"last"} } ,"currentPage":1} )</script></span></td>
<td class="pageExport"><script type="text/javascript" src="/opi/javax.faces.resource/download.js?ln=js/component&amp;b="></script><script type="text/javascript">

我想问一下是否有办法使用 mechanize 点击所有的链接并获取所有页面(请注意,» 符号后面还有更多的页面可用)?我询问对于网络知识完全不懂的人的回答。
2个回答

4
首先,由于这是一个相当“javascript-heavy”的网站,我仍然会坚持使用selenium。请注意,如果需要,您可以使用无头浏览器(PhantomJS虚拟显示)。
这里的想法是每页分页100行,点击“>>”链接直到页面上没有该链接为止,这意味着我们已经到达了最后一页并且没有更多的结果需要处理。为了使解决方案可靠,我们需要使用显式等待:每次我们进入下一页时 - 等待加载旋转器不可见。
有效实现:
# -*- coding: utf-8 -*-
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Firefox()
driver.maximize_window()

driver.get('https://polon.nauka.gov.pl/opi/aa/drh/zestawienie?execution=e1s1')
wait = WebDriverWait(driver, 30)

# paginate by 100
select = Select(driver.find_element_by_id("drhPageForm:drhPageTable:j_idt211:j_idt214:j_idt220"))
select.select_by_visible_text("100")

while True:
    # wait until there is no loading spinner
    wait.until(EC.invisibility_of_element_located((By.ID, "loadingPopup_content_scroller")))

    current_page = driver.find_element_by_class_name("rf-ds-act").text
    print("Current page: %d" % current_page)

    # TODO: collect the results

    # proceed to the next page
    try:
        next_page = driver.find_element_by_link_text(u"»")
        next_page.click()
    except NoSuchElementException:
        break

你的解决方案似乎更好。我开了一个新的悬赏来感谢你的回答 :) - yak
@yak 哇,非常感谢。很高兴这个答案有助于解决问题。 - alecxe

2
这对我很有帮助:看起来所有的HTML都可以在page中使用。
import time    
from selenium import webdriver
driver = webdriver.Firefox()
driver.get('https://polon.nauka.gov.pl/opi/aa/drh/zestawienie')

next_id = 'drhPageForm:drhPageTable:j_idt211:j_idt233_ds_next'

pages = []
it = 0
while it < 1795:
    time.sleep(1)
    it += 1
    bad = True
    while bad:
        try:
            driver.find_element_by_id(next_id).click()
            bad = False 
        except:
            print('retry')

    page = driver.page_source

    pages.append(page)

与其先收集和存储所有的HTML,您也可以只查询您需要的内容,但是这需要使用lxmlBeautifulSoup

编辑:在运行后,我确实注意到我们犯了一个错误。只需捕获异常并重试即可。


非常感谢您的帮助 :) 我一会儿会尝试一下。是的,我同意,但BeautifulSoup不是问题,我以前用过,所以我想我会处理它。然而,我在使用send_keys方法时遇到了问题,因为在我自动(从源代码)点击搜索(Wyszukaj)按钮后,页面会自动清除标准。无论如何,如果您的方法有效,我将简单地使用BS4进行解析。 - yak
哦,我刚注意到,你就是“yagmail”的那个人——我用了你的工具,我想感谢你,它太棒了! - yak
祝你好运!我相信它会起作用 :) 的确,这个页面做了什么很奇怪,但是简单地重试元素就可以解决问题...此外,如果你想友好地对待页面并耐心等待,请随意增加更多的延迟。 - PascalVKooten
@yak 哈哈,被称为“那个人”真是太酷了;不客气! - PascalVKooten
部分地。我正在使用您的解决方案,但似乎它会“重复”某些页面并下载其中一些两次。不过,我认为这不是一个很大的问题,我可以在解析时进一步处理。干杯 :) - yak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接