在Python中抓取更新JavaScript页面
我一直在从事一个研究项目,希望获得一份来自巴西萱草的参考文章列表(所需的页面参考:,需要从以下页面的两个隐藏元素中收集:)。几周前我问了一个问题,这个问题得到了回答,我能够很好地解决这个问题,但现在我遇到了一个新的障碍,我不确定如何克服它 问题是,在填写第一个表单后,页面重定向到第二个页面,这是一个启用JavaScript/AJAX的页面,我需要通过点击页面顶部的按钮来完成所有匹配。我遇到的问题是,当单击“下一页”按钮时,我正在处理页面上正在更新的元素,这会导致过时的元素。我试图实现一些代码来检测何时出现这种“过时”的效果,以指示页面已更改,但这并没有带来多少运气。以下是我实现的代码:在Python中抓取更新JavaScript页面,python,html,selenium,Python,Html,Selenium,我一直在从事一个研究项目,希望获得一份来自巴西萱草的参考文章列表(所需的页面参考:,需要从以下页面的两个隐藏元素中收集:)。几周前我问了一个问题,这个问题得到了回答,我能够很好地解决这个问题,但现在我遇到了一个新的障碍,我不确定如何克服它 问题是,在填写第一个表单后,页面重定向到第二个页面,这是一个启用JavaScript/AJAX的页面,我需要通过点击页面顶部的按钮来完成所有匹配。我遇到的问题是,当单击“下一页”按钮时,我正在处理页面上正在更新的元素,这会导致过时的元素。我试图实现一些代码来检
import urllib
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
import time
saveDir = "C:/tmp"
print("Opening Page...")
browser = webdriver.Chrome()
url = "http://bndigital.bn.gov.br/hemeroteca-digital/"
browser.get(url)
print("Searching for elements")
fLink = ""
fails = 0
frame_ref = browser.find_elements_by_tag_name("iframe")[0]
iframe = browser.switch_to.frame(frame_ref)
journal = browser.find_element_by_id("PeriodicoCmb1_Input")
search_journal = "Relatorios dos Presidentes dos Estados Brasileiros (BA)"
search_timeRange = "1890 - 1899"
search_text = "Milho"
xpath_form = "//input[@name=\'PesquisarBtn1\']"
xpath_journal = "//li[text()=\'"+search_journal+"\']"
xpath_timeRange = "//input[@name=\'PeriodoCmb1\' and not(@disabled)]"
xpath_timeSelect = "//li[text()=\'"+search_timeRange+"\']"
xpath_searchTerm = "//input[@name=\'PesquisaTxt1\']"
print("Locating Journal/Periodical")
journal.click()
dropDownJournal = WebDriverWait(browser, 60).until(EC.presence_of_element_located((By.XPATH, xpath_journal)))
dropDownJournal.click()
print("Waiting for Time Selection")
try:
timeRange = WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.XPATH, xpath_timeRange)))
timeRange.click()
time.sleep(1)
print("Locating Time Range")
dropDownTime = WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.XPATH, xpath_timeSelect)))
dropDownTime.click()
time.sleep(1)
except:
print("Failed...")
print("Adding Search Term")
searchTerm = WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.XPATH, xpath_searchTerm)))
searchTerm.clear()
searchTerm.send_keys(search_text)
time.sleep(5)
print("Perform search")
submitButton = WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.XPATH, xpath_form)))
submitButton.click()
# Wait for the second page to load, pull what we need from it.
download_list = []
browser.switch_to_window(browser.window_handles[-1])
print("Waiting for next page to load...")
matches = WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.XPATH, "//span[@id=\'OcorNroLbl\']")))
print("Next page ready, found match element... counting")
countText = matches.text
countTotal = int(countText[countText.find("/")+1:])
print("A total of " + str(countTotal) + " matches have been found, standing by for page load.")
for i in range(1, countTotal+2):
print("Waiting for page " + str(i-1) + " to load...")
while(fLink in download_list):
try:
jIDElement = browser.find_element_by_xpath("//input[@name=\'HiddenBibAlias\']")
jPageElement = browser.find_element_by_xpath("//input[@name=\'hPagFis\']")
fLink = "http://memoria.bn.br/DocReader/" + jIDElement.get_attribute('value') + "/" + jPageElement.get_attribute('value') + "&pesq=" + search_text
except:
fails += 1
time.sleep(1)
if(fails == 10):
print("Locked on a page, attempting to push to next.")
nextPageButton = WebDriverWait(browser, 5).until(EC.presence_of_element_located((By.XPATH, "//input[@id=\'OcorPosBtn\']")))
nextPageButton.click()
#raise
while(fLink == ""):
jIDElement = browser.find_element_by_xpath("//input[@name=\'HiddenBibAlias\']")
jPageElement = browser.find_element_by_xpath("//input[@name=\'hPagFis\']")
fLink = "http://memoria.bn.br/DocReader/" + jIDElement.get_attribute('value') + "/" + jPageElement.get_attribute('value') + "&pesq=" + search_text
fails = 0
print("Link obtained: " + fLink)
download_list.append(fLink)
if(i != countTotal):
print("Moving to next page...")
nextPageButton = WebDriverWait(browser, 5).until(EC.presence_of_element_located((By.XPATH, "//input[@id=\'OcorPosBtn\']")))
nextPageButton.click()
我正试图用这个块解决两个“bug”。首先,第一页在循环中总是被跳过(即:fLink=“”),即使其中有一个测试,我也不知道为什么会发生这种情况。另一个错误是,代码将完全随机地挂在特定页面上,唯一的出路是中断代码的执行
这个区块已经修改了几次,所以我知道这不是最“优雅”的解决方案,但我开始没有时间了。在休息一天思考(并多睡一会儿)之后,我能够弄清楚到底发生了什么。上述代码有三个“大错误”。首先,它不处理StaleElementException和NosTouchElementException,后者可能在页面移动时发生。其次,循环条件反复检查页面不在列表中,当进入第一次运行时,允许空白状态直接加载,因为循环在第一次运行时从来没有执行过(应该在那里使用一个DO,但我做了更多的修改)。最后,我犯了一个愚蠢的错误,只检查第一个隐藏元素是否在更改,而实际上它是日志ID,并且在所有过程中几乎都是常量 修订开始时,对上的代码进行了修改,以实现“保持”条件,直到其中一个隐藏元素发生更改:
from selenium.common.exceptions import StaleElementReferenceException
from selenium.common.exceptions import NoSuchElementException
def hold_until_element_changed(driver, element1_xpath, element2_xpath, old_element1_text, old_element2_text):
while True:
try:
element1 = driver.find_element_by_xpath(element1_xpath)
element2 = driver.find_element_by_xpath(element2_xpath)
if (element1.get_attribute('value') != old_element1_text) or (element2.get_attribute('value') != old_element2_text):
break
except StaleElementReferenceException:
break
except NoSuchElementException:
return False
time.sleep(1)
return True
然后我修改了原来的循环条件,返回到我创建的没有内部循环的原始“for loop”计数器,而不是调用上面的函数来创建“hold”,直到页面翻转为止,瞧,工作得很好。(注意:我还在下一页按钮上增加了超时,因为这是导致锁定条件的原因)
总而言之,一个好的思维练习和一些有用的链接让我在发表未来的问题时考虑。谢谢 我试图按照你提供的代码与你发布的链接进行对比,但它们似乎不在同一页面上。如果您用文字解释代码中表示的场景,这样我们就可以继续了。另外,在代码开始的页面上发布一个链接,这样我们就可以跟进了。当然,代码希望在特定的日志/时间段内删除所有命中实例。主页是。我已经有了填充表单的代码,它链接到日记账分录(第一个是上面提供的链接)。该程序的目标是从每次点击中获取两个隐藏的表单元素(名称为:hiddenbibbalias和hPagFis)。流程基本上是加载到日志页面,抓取两个隐藏的值并保存它们,然后转到下一页,循环直到完成所有操作。您是在解释程序的实现,而不是目标。你到底想做什么?我怀疑这个计划的目的是寻找隐藏的元素。您是否正在尝试为文档的各个页面捕获URL或下载页面的图像或???您的代码不是一个。您有未声明的变量。你从一个你没有告诉我们的页面开始。您将获得包含URL中随时可用的数据的隐藏元素。我仍然不明白你想做什么。我已经更新了原始帖子,包含了使用的完整代码。该程序的目标是在数据库中运行(使用日志、时间和搜索项的三个定义变量),并捕获单个结果的链接。然而,网站的建立方式,仅仅复制原始链接是不够的,您需要从搜索的每次点击中捕获两个隐藏元素,以便重建结果链接,我希望将其保存到输出文件(.txt)。如果不清楚,我很抱歉,上面的URL是“期望的结果”,是从隐藏字段构建的。
for i in range(1, countTotal+1):
print("Waiting for page " + str(i) + " to load...")
bibxpath = "//input[@name=\'HiddenBibAlias\']"
pagexpath = "//input[@name=\'hPagFis\']"
jIDElement = WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.XPATH, bibxpath)))
jPageElement = WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.XPATH, pagexpath)))
jidtext = jIDElement.get_attribute('value')
jpagetext = jPageElement.get_attribute('value')
fLink = "http://memoria.bn.br/DocReader/" + jidtext + "/" + jpagetext + "&pesq=" + search_text
print("Link obtained: " + fLink)
download_list.append(fLink)
if(i != countTotal):
print("Moving to next page...")
nextPageButton = WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.XPATH, "//input[@id=\'OcorPosBtn\']")))
nextPageButton.click()
# Wait for next page to be ready
change = hold_until_element_changed(browser, bibxpath, pagexpath, jidtext, jpagetext)
if(change == False):
print("Something went wrong.")