使用Wget时,如何正确解析web链接以避免403错误



我昨天刚开始学习python,编码技能非常低。我正在尝试编写一个python脚本,它将处理一个PDF文件夹。每个PDF至少包含1个,可能多达15个或更多的补充文档的网络链接。我认为我有一个良好的开端,但我有着始终如一的";HTTP错误403:禁止";尝试使用wget函数时出错。我相信我只是没有正确解析网络链接。我认为主要的问题出现了,因为网络链接大多是";s3.amazonaws.com";超长的链接。

供参考:

直接从PDF复制的链接(可下载(:https://s3.amazonaws.com/os_uploads/2169504_DFA%20train%20pass.PNG?AWSAccessKeyId=AKIAIPCTK7BDMEW7SP4Q&过期=1909634500&签名=aQlQXVR8UuYLtkzjvcKJ5tiVrZQ=&响应内容处置=附件;%20filename*=utf-8''DFA%2520列车%2520护照.PNG

在我的代码中尝试解析后出现的链接(不起作用,在尝试下载时给出"未知url类型"(:https%3A//s3.amazonaws.com/os_uploads/2169504_DFA%2520train%2520pass.PNG%3FAWSAccessKeyId%3DAKIIPCTK7BDMEW7SP4Q%26过期%3D19099634500%26签名%3DaQlQXVR8UuYLtkzjvcKJ5tiVrZQ%253D%26响应内容处置%3Attachment%253B%2520filename%252A%253Dutf-8%2527%2527DFA%2252520train%2252520pass.PNG

此外,如果人们想权衡我是如何以愚蠢的方式做这件事的。每个PDF都以一个6位数字的字符串开头,一旦我下载了补充文档,我就想自动保存并将其命名为XXXXXX_attachY。*其中X是识别数字的字符串,Y只是随着每个附件的增加而增加。我的代码还没有足够的工作来测试它,但我很确定我的代码也不正确。

救命!

#!/usr/bin/env python3
import os
import glob
import pdfx
import wget
import urllib.parse
## Accessing and Creating Six Digit File Code
pdf_dir = "/users/USERNAME/desktop/worky"
pdf_files = glob.glob("%s/*.pdf" % pdf_dir)
for file in pdf_files:
## Identify File Name and Limit to Digits
filename = os.path.basename(file)
newname = filename[0:6]

## Run PDFX to identify and download links
pdf = pdfx.PDFx(filename)
url_list = pdf.get_references_as_dict()
attachment_counter = (1)
for x in url_list["url"]:
if x[0:4] == "http":
parsed_url = urllib.parse.quote(x, safe='://')
print (parsed_url)
wget.download(parsed_url, '/users/USERNAME/desktop/worky/(newname)_attach(attachment_counter).*')
##os.rename(r'/users/USERNAME/desktop/worky/(filename).*',r'/users/USERNAME/desktop/worky/(newname)_attach(attachment_counter).*')
attachment_counter += 1
for x in url_list["pdf"]:
print (parsed_url + "n")```

我更喜欢使用requests(https://requests.readthedocs.io/en/master/)当试图在线获取文本或文件时。我在wget上快速尝试了一下,但得到了相同的错误(可能链接到wget使用的用户代理HTTP头(。

  • wget和HTTP标头问题:使用python-urllib从url下载图像,但收到HTTP错误403:禁止
  • HTTP标头:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent

requests的好处在于,它允许您按照自己想要的方式修改HTTP标头(https://requests.readthedocs.io/en/master/user/quickstart/#custom-标头(。

import requests
r = requests.get("https://s3.amazonaws.com/os_uploads/2169504_DFA%20train%20pass.PNG?AWSAccessKeyId=AKIAIPCTK7BDMEW7SP4Q&Expires=1909634500&Signature=aQlQXVR8UuYLtkzjvcKJ5tiVrZQ=&response-content-disposition=attachment;%20filename*=utf-8''DFA%2520train%2520pass.PNG")
with open("myfile.png", "wb") as file:
file.write(r.content)

我不确定我是否理解你想做什么,但也许你想使用格式化的字符串来构建你的URL(https://docs.python.org/3/library/stdtypes.html?highlight=format#str.format)?

在您的情况下(if x[0:4] == "http":(,也许检查字符串索引是可以的,但我认为您应该检查pythonre包,以便使用正则表达式来捕获文档中所需的元素(https://docs.python.org/3/library/re.html)。

import re
regex = re.compile(r"^http://")
if re.match(regex, mydocument):
<do something>

这种行为的原因是在wget库中。里面用urllib.parse.quote()编码URL(https://docs.python.org/3/library/urllib.parse.html#urllib.parse.quote)。

基本上,它用相应的%xx转义符替换字符。您的URL已经转义,但库不知道。当它解析%20时,它认为%是一个需要替换的字符,因此结果是%2520和不同的URL,因此出现403错误。

您可以先解码该URL,然后再传递它,但这个库会出现另一个问题,因为您的URL有参数filename*=,但库需要filename=

我建议这样做:

# get the file
req = requests.get(parsed_url)
# parse your URL to get GET parameters
get_parameters = [x for x in parsed_url.split('?')[1].split('&')]
filename = ''
# find the get parameter with the name
for get_parameter in get_parameters:
if "filename*=" in get_parameter:
# split it to get the name
filename = get_parameter.split('filename*=')[1]
# save the file
with open(<path> + filename, 'wb') as file:
file.write(req.content)

我还建议删除该文件名中的utf-8'',因为我不认为它实际上是文件名的一部分。你也可以使用正则表达式来获取文件名,但这对我来说更容易

最新更新