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

2024-06-17 09:08:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我昨天刚开始学习python,而且基本上没有编码技能。我正在尝试编写一个python脚本来处理PDF文件夹。每个PDF包含至少1个,可能多达15个或更多的补充文档的web链接。我想我已经有了一个很好的开始,但是在尝试使用wget函数时,出现了一致的“HTTP错误403:Forbidden”错误。我相信我只是没有正确解析web链接。我认为主要的问题来了,因为网络链接大多是“s3.amazonaws.com”的超长链接

供参考:

直接从PDF复制的链接(下载作品):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

在我的代码中尝试解析后显示的链接(不起作用,尝试下载时给出“未知url类型”):https%3A//s3.amazonaws.com/os_uploads/2169504_DFA%2520train%2520pass.PNG%3FAWSAccessKeyId%3DAKIAIPCTK7BDMEW7SP4Q%26Expires%3D1909634500%26Signature%3daqqxvr8uuuyltkzvckvckj5tivrzq%253D%26响应内容处理%3detaachment%253B%2520filename%252A%253Dutf-8%2527%2527DFA%520train%252520pass.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")```

Tags: importurlattachmentpdfos链接counterusername
2条回答

此行为的原因在wget库中。在它内部,用urllib.parse.quote()https://docs.python.org/3/library/urllib.parse.html#urllib.parse.quote)对URL进行编码

基本上,它用相应的%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'',因为我认为它实际上不是文件名的一部分。您也可以使用正则表达式获取文件名,但这对我来说更容易

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

使用requests的好处是,它允许您以您想要的方式(https://requests.readthedocs.io/en/master/user/quickstart/#custom-headers)修改HTTP头

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>

相关问题 更多 >