需要使用python(selenium)通过ajax加载一个表

需要使用python(selenium)通过ajax加载一个表,python,selenium,selenium-webdriver,Python,Selenium,Selenium Webdriver,我有一个表(table id=“ctl00\u ContentPlaceHolder\u ctl00\u ctl00\u GV”class=“GridListings”)需要刮取。 我通常使用BeautifulSoup&urllib,但在本例中,问题是加载表需要一些时间,因此当我尝试使用BS获取表时,它不会被捕获。 由于一些安装问题,我无法使用PyQt4、drysracpe或windmill,因此唯一可能的方法是使用Selenium/PhantomJS 我尝试了以下方法,但仍然没有成功: fro

我有一个表(table id=“ctl00\u ContentPlaceHolder\u ctl00\u ctl00\u GV”class=“GridListings”)需要刮取。 我通常使用BeautifulSoup&urllib,但在本例中,问题是加载表需要一些时间,因此当我尝试使用BS获取表时,它不会被捕获。 由于一些安装问题,我无法使用PyQt4、drysracpe或windmill,因此唯一可能的方法是使用Selenium/PhantomJS 我尝试了以下方法,但仍然没有成功:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.PhantomJS()
driver.get(url)
wait = WebDriverWait(driver, 10)
table = wait.until(EC.presence_of_element_located(By.CSS_SELECTOR, 'table#ctl00_ContentPlaceHolder_ctl00_ctl00_GV'))
上面的代码没有给出表中所需的内容。
我该如何实现这一点呢?

如果你想废弃一些东西,最好先安装一个web调试器(例如)来观察你想要废弃的网站是如何工作的

接下来,您需要复制网站连接到后台的过程

正如您所说的,您想要废弃的内容正在异步加载(仅当文档准备就绪时)

假设调试器正在运行,并且您已经刷新了页面,您将在“网络”选项卡上看到以下请求:

职位

实现目标的最终流程是:

  • 1/使用
  • 2/打开索引页网站的请求会话(使用cookies处理)
  • 3/放弃特定POST表单请求的所有输入
  • 4/构建一个POST参数DICT,包含上一步中废弃的所有输入和值字段+添加一些特定的固定参数
  • 5/发布请求(提供所需数据)
  • 6/使用finally(像往常一样)来处理已回答的html以废弃数据
请参见以下工作代码:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

from bs4 import BeautifulSoup
import requests

base_url="https://seahawks.strmarketplace.com/Charter-Seat-Licenses/Charter-Seat-Licenses.aspx"

#create requests session
s = requests.session()

#get index page
r=s.get(base_url)

#soup page
bs=BeautifulSoup(r.text)

#extract FORM html
form_soup= bs.find('form',{'name':'aspnetForm'})

#extracting all inputs
input_div = form_soup.findAll("input")

#build the data parameters for POST request
#we add some required <fixed> data parameters for post
data={
    '__EVENTARGUMENT':'LISTINGS;0',
    '__EVENTTARGET':'ctl00$ContentPlaceHolder$ctl00$ctl00$RadAjaxPanel_GV',
    '__EVENTVALIDATION':'/wEWGwKis6fzCQLDnJnSDwLq4+CbDwK9jryHBQLrmcucCgL56enHAwLRrPHhCgKDk6P+CwL1/aWtDQLm0q+gCALRvI2QDAKch7HjBAKWqJHWBAKil5XsDQK58IbPAwLO3dKwCwL6uJOtBgLYnd3qBgKyp7zmBAKQyTBQK9qYAXAoieq54JAuG/rDkC1djKyQMC1qnUtgoC0OjaygUCv4b7sAhfkEODRvsa3noPfz2kMsxhAwlX3Q=='
}
#we add some <dynamic> data parameters
for input_d in input_div:
    try:
        data[ input_d['name'] ] =input_d['value'] 
    except:
        pass #skip unused input field

#post request
r2=s.post(base_url,data=data)

#write the result
with open("post_result.html","w") as f:
    f.write(r2.text.encode('utf8'))
#/usr/bin/env python
#-*-编码:UTF-8-*-
从bs4导入BeautifulSoup
导入请求
基本url=”https://seahawks.strmarketplace.com/Charter-Seat-Licenses/Charter-Seat-Licenses.aspx"
#创建请求会话
s=请求。会话()
#获取索引页
r=s.get(基本url)
#汤页
bs=美化组(右文本)
#提取表单html
form_soup=bs.find('form',{'name':'aspnetForm'})
#提取所有输入
input\u div=form\u soup.findAll(“输入”)
#为POST请求构建数据参数
#我们为post添加了一些必需的数据参数
资料={
“\uu EVENTARGUMENT”:“清单;0”,
“_EVENTTARGET”:“ctl00$ContentPlaceHolder$ctl00$ctl00$RadAjaxPanel_GV”,
“事件验证”:/wEWGwKis6fzCQLDnJnSDwLq4+CBDWK9JRYHBQLRMCUCCGL56ENHAWLRPHCHCGDK6P+CwL1/aWtDQLm0q+GCALRVI2QDAKCH7HJBAKWQJWBAKI5XSDQK58IBPAWLO3KWKWKWL6UJOTBGLYD3QBKYP7ZMBKYTK9QYAXAOIEQ54JAUG/RDKMS1JKYQMC1QNUTGOGOJAYGUKKYG7SAH7CF7SAH3KH3KH3KW3Q='
}
#我们添加了一些数据参数
对于input_div中的input_d:
尝试:
数据[input_d['name']]=input_d['value']
除:
通过#跳过未使用的输入字段
#后请求
r2=s.post(基本url,数据=数据)
#写出结果
以open(“post_result.html”、“w”)作为f:
f、 写入(r2.text.encode('utf8'))
现在,请查看“post_result.html”内容,您将找到数据


关于

您可以使用请求和bs4获取数据,对于几乎所有的asp站点,都需要提供一些post参数,如_EVENTTARGET、_EVENTVALIDATION等:

对于实际的post,我们需要为out post数据添加更多值:

post = "https://seahawks.strmarketplace.com/Charter-Seat-Licenses/Charter-Seat-Licenses.aspx"
with requests.Session() as s:
    s.headers.update({"User-Agent":"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0"})
    soup = BeautifulSoup(s.get(post).content)

    data["__VIEWSTATEGENERATOR"] = soup.select_one("#__VIEWSTATEGENERATOR")["value"]
    data["__EVENTVALIDATION"] = soup.select_one("#__EVENTVALIDATION")["value"]
    data["__VIEWSTATE"] = soup.select_one("#__VIEWSTATE")["value"]

    r = s.post(post, data=data)
    soup2 = BeautifulSoup(r.content)
    table = soup2.select_one("div.GridListings")
    print(table)

当您运行代码时,您将看到打印的表格。

什么意思不给我所需的内容??有什么例外吗??您能在这里分享您的表格HTML吗?您好,下面的表格就是我想要的(带有class=“GridListings”的表格)很抱歉,这次我无法查看表格,这就是为什么我告诉你在这里共享表格HTML。你检查了页面的post参数了吗?我认为这行不通。如果你查看了post requestYear,你就会明白,这就是为什么我在过程中添加了步骤3和步骤4,在接下来的5分钟内,我将用一个工作代码更新我的答案。感谢您的努力,但仍然没有捕获该表:查看输出文件,该表将出现在下面的innerdiv中,它仍然是空的Yes,表div是空的,这是对的:-),但是文档中有更多的数据可见(我们可以看到示例部分)。我们可能需要在更新后的请求代码中添加固定标题和/或某些数据参数:添加_EVENTARGUMENT、_EVENTTARGET、_EVENTVALIDATION是必需的数据参数您完全正确!!!!!我现在可以看到桌子了。非常感谢!!!但是我有一个疑问,因为我们静态地在页面上发布了几个参数,所以不可能下载同一个页面,对吗?我的意思是,每次我们运行这个表时,表都会更新,对吗?@user3425403,是的,我们只是在进行所需的验证,您还可以传递更多的参数,我还没有全部看过,但您应该能够通过添加更多内容来影响数据的返回方式。是否有方法确定哪些是所需的表单数据?
post = "https://seahawks.strmarketplace.com/Charter-Seat-Licenses/Charter-Seat-Licenses.aspx"
with requests.Session() as s:
    s.headers.update({"User-Agent":"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0"})
    soup = BeautifulSoup(s.get(post).content)

    data["__VIEWSTATEGENERATOR"] = soup.select_one("#__VIEWSTATEGENERATOR")["value"]
    data["__EVENTVALIDATION"] = soup.select_one("#__EVENTVALIDATION")["value"]
    data["__VIEWSTATE"] = soup.select_one("#__VIEWSTATE")["value"]

    r = s.post(post, data=data)
    soup2 = BeautifulSoup(r.content)
    table = soup2.select_one("div.GridListings")
    print(table)