【问题标题】:Scrape table through iteration only after data loads with delay using Python?仅在使用 Python 延迟加载数据后通过迭代刮表?
【发布时间】:2018-12-03 05:35:16
【问题描述】:

我正在尝试使用 python(Requests 和 BeautifulSoup4 库以及 Selenium)来抓取数据

当我尝试从网站中获取一些数据时,在延迟后加载数据时,它返回一个空值。我知道对于这项任务,我必须使用 WebDriverWait。

import requests
from bs4 import BeautifulSoup
# selenium imports
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import TimeoutException

# Initialize a Chrome webdriver
driver = webdriver.Chrome()

# Grab the web page
driver.get("http://")

# use selenium.webdriver.support.ui.Select
# that we imported above to grab the Select element called 
# lmStatType, then select the first value

# We will use .find_element_by_name here because we know the name
dropdown = Select(driver.find_element_by_name("lmStatType"))
dropdown.select_by_value("1")

# select the year 2560
dropdown = Select(driver.find_element_by_name("lmYear"))
dropdown.select_by_value("60")

# Now we can grab the search button and click it
search_button = driver.find_elements_by_xpath("//*[contains(text(), 'ตกลง')]"[0]
search_button.click()

# we just look at .page_source of the driver
driver.page_source

# We can feed that into Beautiful Soup
doc = BeautifulSoup(driver.page_source, "html.parser")

# It's a tricky table, also tried with class names
rows = doc.find('table', id='datatable')
print(rows) # returns empty

在上面的例子中,我没有使用 selenium webdriver wait & timeout 相关语句的尝试选项来逐步理解它,即使我已经尝试了几种解决方法。

另外,刚刚尝试分别获取地区级别的数据(但无法弄清楚确切的类/id)

url = 'http://'
res = requests.get(url)
soup = BeautifulSoup(res.text,"lxml")
for tr in soup.find(class_="display").find_all("tr"):
    data = [item.get_text(strip=True) for item in tr.find_all(["th","td"])]
    print(data)

感谢任何帮助。提前致谢。抱歉,如果这是一个重复的问题。

【问题讨论】:

  • 如果您可以直接从 /datasource/showStatProvince.php?statType=1&year=60" 获取数据 - 那可能会容易得多...
  • 无法直接从url获取数据,因为是通过js函数处理的
  • 当然可以。 HTML 中的 javascript-funktion 实际上为您提供了直接获取数据的正确 url。该端点返回 json...
  • 不幸的是,一旦您发布,您就无法删除。您必须使用底部的联系我们链接请求解除关联。

标签: python selenium web-scraping beautifulsoup python-requests


【解决方案1】:

正如我在评论中所说,html 实际上为您提供了获取数据的端点。从那以后,使用请求获取数据实际上非常容易。

在您的 html 中显示为:“sAjaxSource”:“../datasource/showStatProvince.php?statType=1&year=60”。这是站点使用的端点。所以你只需要在网站的 url 结构中返回一级并使用“/datasource/....”来代替

看看:

import requests
from bs4 import BeautifulSoup
import re

url = "http://stat.bora.dopa.go.th/stat/statnew/statTDD/datasource/showStatDistrict.php?statType=1&year=60&rcode=10"

r = requests.get(url)
# endpoint returns json
data = r.json()
aaData = data['aaData']

# this base url for viewing the details for each hit
view_url = "http://stat.bora.dopa.go.th/stat/statnew/statTDD/views/showZoneData.php"

# the first line in the dataset is actually html
# we convert this to plain text
html_header = aaData[0]
html_header_stripped = [BeautifulSoup(e, "html.parser").get_text() for e in html_header]

# and the insert this html_header_stripped in the aaData-list
aaData[0] = html_header_stripped
for rcode, region_html,male,female, total, home in aaData:
    # first element is "<font color='red'><b>กรุงเทพมหานคร</b></font>"
    # secound is "<a href=javascript:openWindow('?rcode=1001&statType=1&year=60')>ท้องถิ่นเขตพระนคร</a>"
    # we need to extract the link that opens in new window to be able to iterate further
    soup = BeautifulSoup(region_html, "html.parser")
    region = soup.get_text()
    try:
        link_element = soup.find('a').get('href')
        rel_link = re.search("\('(.+)'\)", link_element).group(1)
        abs_link = view_url + rel_link
    except:
        abs_link = None

    print("{};{};{};{};{};{};{}".format(rcode, region, abs_link,male,female,total,home))

我在这里打印结果,但假设您想跟踪链接并获取该数据,您可以将结果存储在 dicts 列表中并随后对其进行迭代或在 for 循环中执行。

【讨论】:

  • 感谢您的回复。事实上,那时甚至不需要使用硒。
  • 不。如果它解决了您的问题,请接受 qnswer。当所有逆向工程都失败时,Selenium 应该是你绝对的最后手段......
  • 为什么又把答案的accept去掉了?如果你想问另一个关于列表和字典如何在 Python 中工作的问题,请这样做,但这些完全是其他问题。所以不是'请给我写一个刮板'-中心。我很乐意为你这样做。作为开发人员,我每小时收费 200 美元。
  • 您提供的答案确实有帮助,但我正在寻找端到端的自动化。以前从未从事过动态响应式抓取。对不起,杰劳尔
  • 不应该。把它放在一个列表中并循环遍历它。我已经向你展示了如何刮掉一个。只需用 for 循环循环它...
猜你喜欢
  • 2018-03-16
  • 2020-05-27
  • 1970-01-01
  • 2011-07-16
  • 2017-10-07
  • 2016-11-02
  • 2014-02-13
  • 1970-01-01
  • 2022-12-22
相关资源
最近更新 更多