即使使用 requests.history,从重定向 2 次的 url 下载 pdf 文件也会失败
Downloading a pdf file from a url that redirects 2 times fails even when using requests.history
我为此苦恼了一整天。我通过在网页上使用 urllib3(也使用 BeautifulSoup)编译了一个 URL 的列表。 URLs 基本上指向我想自动下载的 pdf 文件。很棒的是 pdf link 有漂亮的图案。所以我很容易使用正则表达式来列出我想要下载的 pdf 并忽略其余部分。但这就是问题的开始。 URL 遵循模式 http://www.ti.com/lit/sboa263
注意:最后一部分针对其他文件进行了更改,并且没有 pdf 文件扩展名。
但是如果你把这个 link 放在你的浏览器中你可以清楚地看到它从那个变成 http://www.ti.com/general/docs/lit/getliterature.tsp?baseLiteratureNumber=sboa263 and that eventually changes to http://www.ti.com/lit/an/sboa263/sboa263.pdf
现在我明白你可以告诉我 "Great, follow this pattern then"。但我不想因为 IMO 这不是解决此自动化的正确方法。我希望能够从第一个 link 本身下载 pdf。
我已经尝试了
response = requests.get(url,allow_redirects=True)</pre>
,它只会将我带到第一个重定向的结果,而不是最后一个文件。
即使 response.history
也只带我到第一个重定向。
当我尝试在那里下载文件时,我得到了一个无法打开的损坏的 pdf。然而,当我手动通过最终 URL 只是为了测试我的文件写入的正确性时,我得到了完美顺序的实际 pdf。
我不明白为什么 requests 无法到达最后的 URL。
我的完整代码如下供您参考 -
from bs4 import BeautifulSoup
import urllib3
import re
http = urllib3.PoolManager()
url = 'http://www.ti.com/analog-circuit/circuit-cookbook.html'
response = http.request('GET', url)
soup = BeautifulSoup(response.data)
find = re.compile("http://www.ti.com/lit/")
download_links = []
for link in soup.find_all('a'):
match = re.match(find, link.get('href'))
if match:
#print(link.get('href'))
download_links.append(link.get('href'))
为了到达重定向的 URL 我使用 -
import requests
response = requests.get(download_links[45])
if response.history:
print ("Request was redirected")
for resp in response.history:
final_url = resp.url
response = requests.get(final_url)
为了下载文件,我使用了下面的代码 -
with open('C:/Users/Dell/Desktop/test.pdf', 'wb') as f:
f.write(response.content)
此外,我实际上只想传递一个文件夹名称,所有文件都应使用 URL 本身最后一部分的名称下载。我还没有弄清楚该怎么做。我尝试了 shutils 但它没有用。如果你也能帮我解决那部分,那就太好了。
编辑:我将前两个 URL 传递给了 Postman,我得到了 HTML,而传递了第三个 URL 下载了 pdf。在我得到的 HTML 中,我可以清楚地看到其中一个 Meta 属性列出了最终的 pdf URL。这是相关的 Postman 结果的一部分 -
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta content="IE=8;IE=9;IE=edge" http-equiv="x-ua-compatible">
<meta content='width=device-width, initial-scale=1.0' name='viewport'>
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="-1">
<META HTTP-EQUIV="Refresh" CONTENT="1; URL=http://www.ti.com/lit/an/sboa263/sboa263.pdf">
下面的部分也显示了最终的 URL,但我想您明白了。我们可以利用这些信息吗?
正如 Miraj50 所提到的,它确实是一个元刷新将它带到了最后 url。所以我从元标记中提取了最后的 urls 并且能够下载所有 45 个 pdf。下面是相同的代码 -
for links in download_links[5:]:
response = requests.get(links)
if response.history:
print ("Request was redirected")
print(response.url)
r = response.url
从元标记获取链接 -
# The redirected url then uses meta refresh
meta_response = http.request('GET', r)
meta_soup = BeautifulSoup(meta_response.data)
meta_result = meta_soup.find('meta',attrs={'http-equiv':'Refresh'})
#print(meta_result)
wait,text = meta_result["content"].split(";")
final_url = text.strip()[4:]
我为此苦恼了一整天。我通过在网页上使用 urllib3(也使用 BeautifulSoup)编译了一个 URL 的列表。 URLs 基本上指向我想自动下载的 pdf 文件。很棒的是 pdf link 有漂亮的图案。所以我很容易使用正则表达式来列出我想要下载的 pdf 并忽略其余部分。但这就是问题的开始。 URL 遵循模式 http://www.ti.com/lit/sboa263
注意:最后一部分针对其他文件进行了更改,并且没有 pdf 文件扩展名。
但是如果你把这个 link 放在你的浏览器中你可以清楚地看到它从那个变成 http://www.ti.com/general/docs/lit/getliterature.tsp?baseLiteratureNumber=sboa263 and that eventually changes to http://www.ti.com/lit/an/sboa263/sboa263.pdf
现在我明白你可以告诉我 "Great, follow this pattern then"。但我不想因为 IMO 这不是解决此自动化的正确方法。我希望能够从第一个 link 本身下载 pdf。
我已经尝试了
response = requests.get(url,allow_redirects=True)</pre>
,它只会将我带到第一个重定向的结果,而不是最后一个文件。 即使response.history
也只带我到第一个重定向。当我尝试在那里下载文件时,我得到了一个无法打开的损坏的 pdf。然而,当我手动通过最终 URL 只是为了测试我的文件写入的正确性时,我得到了完美顺序的实际 pdf。 我不明白为什么 requests 无法到达最后的 URL。 我的完整代码如下供您参考 -
from bs4 import BeautifulSoup import urllib3 import re http = urllib3.PoolManager() url = 'http://www.ti.com/analog-circuit/circuit-cookbook.html' response = http.request('GET', url) soup = BeautifulSoup(response.data) find = re.compile("http://www.ti.com/lit/") download_links = [] for link in soup.find_all('a'): match = re.match(find, link.get('href')) if match: #print(link.get('href')) download_links.append(link.get('href'))
为了到达重定向的 URL 我使用 -
import requests response = requests.get(download_links[45]) if response.history: print ("Request was redirected") for resp in response.history: final_url = resp.url response = requests.get(final_url)
为了下载文件,我使用了下面的代码 -
with open('C:/Users/Dell/Desktop/test.pdf', 'wb') as f: f.write(response.content)
此外,我实际上只想传递一个文件夹名称,所有文件都应使用 URL 本身最后一部分的名称下载。我还没有弄清楚该怎么做。我尝试了 shutils 但它没有用。如果你也能帮我解决那部分,那就太好了。
编辑:我将前两个 URL 传递给了 Postman,我得到了 HTML,而传递了第三个 URL 下载了 pdf。在我得到的 HTML 中,我可以清楚地看到其中一个 Meta 属性列出了最终的 pdf URL。这是相关的 Postman 结果的一部分 -
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta content="IE=8;IE=9;IE=edge" http-equiv="x-ua-compatible"> <meta content='width=device-width, initial-scale=1.0' name='viewport'> <META HTTP-EQUIV="Pragma" CONTENT="no-cache"> <META HTTP-EQUIV="Expires" CONTENT="-1"> <META HTTP-EQUIV="Refresh" CONTENT="1; URL=http://www.ti.com/lit/an/sboa263/sboa263.pdf">
下面的部分也显示了最终的 URL,但我想您明白了。我们可以利用这些信息吗?
正如 Miraj50 所提到的,它确实是一个元刷新将它带到了最后 url。所以我从元标记中提取了最后的 urls 并且能够下载所有 45 个 pdf。下面是相同的代码 -
for links in download_links[5:]:
response = requests.get(links)
if response.history:
print ("Request was redirected")
print(response.url)
r = response.url
从元标记获取链接 -
# The redirected url then uses meta refresh
meta_response = http.request('GET', r)
meta_soup = BeautifulSoup(meta_response.data)
meta_result = meta_soup.find('meta',attrs={'http-equiv':'Refresh'})
#print(meta_result)
wait,text = meta_result["content"].split(";")
final_url = text.strip()[4:]