【问题标题】:How do I wait through a wait page and then download a PDF, using Python?如何通过等待页面等待,然后使用 Python 下载 PDF?
【发布时间】:2016-06-21 19:38:43
【问题描述】:

问题

我正在尝试从一个建立在一个古怪的旧大型机上的网站下载 PDF 文件,为了支持流量,该网站实施了等待页面。等待页面将呈现,您将花几秒钟时间查看它而不是您想要的 PDF,然后它会消失,您会去您想去的地方。

这是我的场景:

  1. 我转到页面。
  2. 可能有 33% 的时间,我得到了等待页面。这是等待页面代码:

<div id="wrapper">
    <p><hr /></p>
    </p>
        <div id="waiting-main">
            <p style="text-align: center; margin: 6px 0 15px 0;"><img src="/ns_images2/doblogo_1.jpg" border="0" />
            </p>
            <p style="text-align: center; font-size: 30px; line-height: 34px;">Just a moment</p>
            <p style="text-align: left; color: #525252; font-size: 20px; line-height: 22px;">
            Your request is being processed.</br></br>

            Due to the high demand it may take a little longer. You will be directed to the page shortly. Please do not leave this page. Refreshing the page will delay the response time. We apologize for the delay.</br></br>

            ...[snipped for brevity]...

            </p>

        </div>

    </div>

</body></html>

  1. 等待页面退出,我加载以下 HTML:

<html><body marginwidth="0" marginheight="0" style="background-color: rgb(38,38,38)"><embed width="100%" height="100%" name="plugin" src="http://a810-bisweb.nyc.gov/bisweb/CofoDocumentContentServlet?passjobnumber=null&amp;cofomatadata1=cofo&amp;cofomatadata2=M&amp;cofomatadata3=000&amp;cofomatadata4=092000&amp;cofomatadata5=M000092531.PDF&amp;requestid=5" type="application/pdf"><div id="annotationContainer"><style>#annotationContainer {    overflow: hidden;     position: absolute;     pointer-events: none;     top: 0;     left: 0;     right: 0;     bottom: 0;     display: -webkit-box;     -webkit-box-align: center;     -webkit-box-pack: center; } .annotation {     position: absolute;     pointer-events: auto; } textarea.annotation {     resize: none; } input.annotation[type='password'] {     position: static;     width: 200px;     margin-top: 100px; } </style></div></body></html>

  1. 我在本地下载 PDF 文档。结束!

我尝试的解决方案

不知道 selenium 并不真正支持 PDF(或者支持吗?),这是我的方法:

_driver = webdriver.PhantomJS()

... 
req_string = ...[a very long URL]...
_driver.get(req_str)
...

try:
    WebDriverWait(_driver, 10).until(
        # Cannot use:
        # lambda a: not a.presence_of_element_located((By.ID, "waiting-main"))
        # Because:
        # https://blog.mozilla.org/webqa/2012/07/12/how-to-webdriverwait/
        # Which suggests this working alternative.
        lambda s: len(s.find_elements(By.ID, "waiting-main")) == 0
    )
finally:
    _driver.save_screenshot("test.png") # Maybe?
    # How do I get the actual PDF code? :/

问题

我看不出用硒做这件事的方法。所以我的问题是:

如何加载页面,等待等待页面,然后使用 Python (2.7) 下载随后提供的 PDF?

或者,如果这个 可以使用 selenium,我该怎么做?

例子

The link on this page exemplifies my problem.

解决方法

目前我正在使用:

r = requests.get(req_str)
while "waiting-main" in r.text:
    time.sleep(5)
    r = requests.get(req_str)

目前还没有关于它的效果如何......

页面

【问题讨论】:

  • 您可以使用WebDriverWait(driver, 10).until_not(something_to_disappear) 等待加载程序窗口关闭。至于第二部分,我不确定我是否理解正确"PDF that comes afterwards"...你的意思是什么?
  • 不幸的是,我的描述因对我要解决的问题的不完全理解而受到阻碍。我已对其进行了更新,以尝试使我的问题更加清晰 - 欢迎提供反馈!
  • 如果您仔细观察,您会注意到pdf 实际上有一个您可以直接点击的网址。如果你能弄清楚那个 URL 是如何构造的,你就可以缩短整个过程。
  • 这正是我点击的链接,实际上; CofoDocumentContentServlet 偶尔会提供等待通知。

标签: python http selenium pdf download


【解决方案1】:

我可以使用请求一致地获取页面源,这将获取 pdf 链接并保存:

from  bs4 import BeautifulSoup
import requests
from urlparse import urljoin

# gets the page when you click the pdf link in your browser
post_url = "http://a810-bisweb.nyc.gov/bisweb/CofoJobDocumentServlet"
base = "http://a810-bisweb.nyc.gov/bisweb/"
r = requests.get("http://a810-bisweb.nyc.gov/bisweb/COsByLocationServlet?requestid=4&allbin=1006360")

soup = BeautifulSoup(r.content)
# parse the form key/value pairs
form_data = {inp["name"]: inp["value"] for inp in soup.select("form[action=CofoJobDocumentServlet] input")}
# post to from data
nr = requests.post(post_url, data=form_data)
soup = BeautifulSoup(nr.content)

# get the link to the pdf to download
pdf = urljoin(base, soup.select_one("iframe")["src"])

# save pdf to file.
with open("out.pdf","wb") as out:
    out.write(requests.get(pdf).content)

如果您遇到等待问题,您可以等到表单在 selenium 中可见,然后将源传递给 bs4:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


def wait(dr, x, t):
    element = WebDriverWait(dr, t).until(
        EC.presence_of_all_elements_located((By.XPATH, x))
    )
    return element

dr = webdriver.PhantomJS()
dr.get("http://a810-bisweb.nyc.gov/bisweb/COsByLocationServlet?requestid=4&allbin=1006360")

wait(dr, "//form[@action='CofoJobDocumentServlet']", 30)

post_url = "http://a810-bisweb.nyc.gov/bisweb/CofoJobDocumentServlet"
base = "http://a810-bisweb.nyc.gov/bisweb/"

soup = BeautifulSoup(dr.page_source)

form_data = {inp["name"]: inp["value"] for inp in soup.select("form[action=CofoJobDocumentServlet] input")}

nr = requests.post(post_url, data=form_data)
soup = BeautifulSoup(nr.content)

pdf = urljoin(base, soup.select_one("iframe")["src"])

with open("out.pdf","wb") as out:
    out.write(requests.get(pdf).content)

【讨论】:

  • 嗯。我不确定这是否能解决我的问题。 requests.get(pdf) 和等待有什么关系?那不是一个单独的过程会再次导致等待时间增加吗?
  • @ResMar,哪个请求会导致等待?
  • 在其界面中对网页的任何请求都可以生成等待页面。也就是说,尝试加载包含 PDF 列表的页面和加载 PDF 本身都可以生成它。我最终使用了一个愚蠢的五秒规则等待时间,以防我点击等待页面,源代码here
【解决方案2】:

我会忽略等待页面。找到下载页面上存在但在等待页面上不存在的特定元素并等待它。只要确保您等待的时间足够长,等待页面肯定会消失(可能是 30 秒或更长时间?您可能需要尝试一下,看看效果如何)。

根据您提供的 HTML,您似乎可以等待 EMBED 元素。我建议使用 WebDriverWait 并使用 CSS 选择器 "embed[name='plugin']"

您可以在此处找到有关 Selenium 等待 Python 的更多信息:http://selenium-python.readthedocs.io/waits.html

【讨论】:

    【解决方案3】:

    您需要为 PDFS 设置下载路径并添加始终在外部打开 pdf 的选项

    driver_path = "path_from_chromedriver"
    download_path = "./PdfFolder"
    optionsSelenium = Options() // from selenium.webdriver.chrome.options import Options
    optionsSelenium.add_experimental_option('prefs',  {
        "download.default_directory": download_path,
        "download.prompt_for_download": False,
        "download.directory_upgrade": True,
        "plugins.always_open_pdf_externally": True
        }
    )
    driver = webdriver.Chrome(executable_path=driver_path, chrome_options=options)
    

    始终显示带有 PDF 的页面只会下载内容并关闭新标签

    【讨论】:

      猜你喜欢
      • 2018-07-08
      • 2016-10-13
      • 2017-03-27
      • 1970-01-01
      • 1970-01-01
      • 2021-03-11
      • 1970-01-01
      • 2019-06-11
      • 1970-01-01
      相关资源
      最近更新 更多