【问题标题】:Scraping dynamic DataTable of many pages but same URL抓取许多页面但 URL 相同的动态 DataTable
【发布时间】:2023-03-23 19:55:02
【问题描述】:

我有 C 方面的经验,我开始接触 Python,主要是为了好玩。 我正在尝试在这里https://www.justetf.com/it/find-etf.html?groupField=index&from=search&/it/find-etf.html%3F1-1.0-esearch-etfsPanel 抓取此页面。 由于包含我感兴趣的内容的表格是在连接到页面后动态创建的,因此我正在使用:

  • Selenium 在浏览器中加载页面
  • 美丽的汤4用于抓取加载的数据

目前,我能够抓取前 25 个条目的所有感兴趣的字段,这些条目一旦连接到页面就会加载。我在一页中最多可以有 100 个条目,但总共有 1045 个条目,它们被分成不同的页面。问题是所有页面的 url 都是相同的,并且表格的内容是在运行时动态加载的。 我想做的是找到一种能够抓取所有条目的方法,即 1045。通过互联网阅读,我知道我应该发送一个正确的 POST 请求(我还发现他们正在从@检索数据987654322@) 从我的代码中,从响应中获取数据并抓取它。 我可以看到两种可能性:

  1. 一次检索所有条目
  2. 一个接一个地检索,然后一个接一个地抓取

我不知道如何构建 POST 请求。 我认为没有必要发布代码,但如果需要,我可以重新编辑问题。 在此先感谢大家。

已编辑

这里有一些代码

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
from bs4 import BeautifulSoup
import requests

firefox_binary = FirefoxBinary('some path\\firefox.exe')
browser = webdriver.Firefox(firefox_binary=firefox_binary)
                                 
url = "https://www.justetf.com/it/find-etf.html"
browser.get(url)
delay = 5 # seconds
try:
myElem = WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, 'Alerian')))
print("Page is ready!")
except TimeoutException:
print ("Loading took too much time!")

page_source = browser.page_source 
soup = BeautifulSoup(page_source, 'lxml')

从这里开始,我只是玩了一下 bs4 API。

【问题讨论】:

  • 加载页面时重定向到https://www.justetf.com/de-en/。我们需要登录吗?如果没有 - 你想刮什么桌子?另外请编辑您已经尝试过的代码。
  • 感谢@MendelG,在描述中进行了编辑。您无需登录。

标签: python selenium beautifulsoup datatables screen-scraping


【解决方案1】:

这应该可以解决问题(一次获取所有数据):

import requests as r

link = 'https://www.justetf.com/it/find-etf.html?groupField=index&from=search&/it/find-etf.html%3F1-1.0-esearch-etfsPanel'
link2 = 'https://www.justetf.com/servlet/etfs-table'

data = {
    'draw': 1,
    'start': 0,
    'length': 10000000,
    'lang': 'it',
    'country': 'DE',
    'universeType': 'private',
    'etfsParams': link.split('?')[1]
}


res = r.post(link2, data=data)
result = res.json()
print(len(result["data"]))

编辑:为了解释,我确实在 chrome 中打开了网络选项卡,然后单击下一页查看已发出的请求,我注意到向 link2 发出了一个带有很多参数的 POST 请求大多数是强制性的。 对于所需的参数,draw我只需要一次绘制(一个请求),start从位置 0 开始,length我使用了一个大数字一次刮掉所有东西。例如,如果长度为 10,您将需要大量的平局,例如draw=2&start=10&length=10draw=3&start=20&length=10 等等。对于langcountryuniverseType,我不知道具体用途,但删除它们会拒绝请求。最后etfsParams 是“?”之后的内容。在link

【讨论】:

  • 哇,这很完美,有了这个解决方案,我什至不需要使用 selenium 甚至 bsp4。在您的回答中,有点缺乏解释。你介意解释一下你是如何得到这个结果的吗?为什么是这些参数?你是如何得到参数和链接的?我也会对理解问题的过程感兴趣。提前非常感谢。
  • 我确实添加了一个快速解释,如果有不清楚的地方,请随时提及该部分,以便我可以详细说明。
  • 再次感谢!如果可能的话,我想进一步了解一件事,您是如何理解哪些是必填字段?如何调试 POST 请求的代码?
  • 通常它们都是强制性的,但这曾经有大量的字段,就像列[1][2] 有不同的数字等等,所以我只是想为什么不删除它们,它最终工作了.可能没有检查这些字段的背景。
猜你喜欢
  • 2016-05-24
  • 1970-01-01
  • 1970-01-01
  • 2023-01-26
  • 2019-11-21
  • 1970-01-01
  • 1970-01-01
  • 2022-07-31
  • 1970-01-01
相关资源
最近更新 更多