डाउनलोड और पीडीएफ फाइल को पायथन अनुरोध मॉड्यूल के साथ सहेजें


86

मैं एक वेबसाइट से एक पीडीएफ फाइल डाउनलोड करने और इसे डिस्क पर सहेजने का प्रयास कर रहा हूं। मेरे प्रयास या तो एन्कोडिंग त्रुटियों के साथ विफल होते हैं या रिक्त PDF में परिणाम करते हैं।

In [1]: import requests

In [2]: url = 'http://www.hrecos.org//images/Data/forweb/HRTVBSH.Metadata.pdf'

In [3]: response = requests.get(url)

In [4]: with open('/tmp/metadata.pdf', 'wb') as f:
   ...:     f.write(response.text)
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
<ipython-input-4-4be915a4f032> in <module>()
      1 with open('/tmp/metadata.pdf', 'wb') as f:
----> 2     f.write(response.text)
      3 

UnicodeEncodeError: 'ascii' codec can't encode characters in position 11-14: ordinal not in range(128)

In [5]: import codecs

In [6]: with codecs.open('/tmp/metadata.pdf', 'wb', encoding='utf8') as f:
   ...:     f.write(response.text)
   ...: 

मुझे पता है कि यह किसी प्रकार की एक कोडेक समस्या है, लेकिन मुझे लगता है कि यह काम करने के लिए नहीं मिल सकता है।

जवाबों:


172

आपको response.contentइस मामले में उपयोग करना चाहिए :

with open('/tmp/metadata.pdf', 'wb') as f:
    f.write(response.content)

से दस्तावेज़ :

आप गैर-पाठ अनुरोधों के लिए प्रतिक्रिया बॉडी को बाइट्स के रूप में एक्सेस कर सकते हैं:

>>> r.content
b'[{"repository":{"open_issues":0,"url":"https://github.com/...

तो इसका मतलब है: response.textआउटपुट को एक स्ट्रिंग ऑब्जेक्ट के रूप में लौटाएं, जब आप एक टेक्स्ट फ़ाइल डाउनलोड कर रहे हों तो इसका उपयोग करें । जैसे कि HTML फ़ाइल, आदि।

और response.contentआउटपुट को बाइट्स ऑब्जेक्ट के रूप में लौटाते हैं, बाइनरी फ़ाइल डाउनलोड करते समय इसका उपयोग करें । जैसे पीडीएफ फाइल, ऑडियो फाइल, इमेज आदि।


आप response.rawइसके बजाय उपयोग कर सकते हैं । हालाँकि, इसका उपयोग तब करें जब आप जिस फ़ाइल को डाउनलोड करने वाले हैं वह बड़ी हो। नीचे एक मूल उदाहरण है जिसे आप दस्तावेज़ में भी देख सकते हैं:

import requests

url = 'http://www.hrecos.org//images/Data/forweb/HRTVBSH.Metadata.pdf'
r = requests.get(url, stream=True)

with open('/tmp/metadata.pdf', 'wb') as fd:
    for chunk in r.iter_content(chunk_size):
        fd.write(chunk)

chunk_sizeचंक आकार है जिसका आप उपयोग करना चाहते हैं। यदि आप इसे सेट करते हैं 2000, तो अनुरोध उस फ़ाइल को पहले 2000बाइट्स को डाउनलोड करेगा , उन्हें फ़ाइल में लिखें, और इसे फिर से, फिर से और फिर से करें, जब तक कि यह समाप्त न हो जाए।

तो इससे आपकी RAM बच सकती है। लेकिन मैं response.contentइस मामले में उपयोग करना पसंद करूंगा क्योंकि आपकी फ़ाइल छोटी है। जैसा कि आप देख सकते हैं उपयोग response.rawजटिल है।


संबंधित है:


Cool, response.raw के बारे में अतिरिक्त जानकारी के लिए धन्यवाद।
जिम

22

पायथन 3 में, मुझे लगता है कि पाथलिब ऐसा करने का सबसे आसान तरीका है। रिक्वेस्ट का रिस्पांस । कंटालिब के राइट_बीट्स के साथ अच्छी तरह से शादी करता है।

from pathlib import Path
import requests
filename = Path('metadata.pdf')
url = 'http://www.hrecos.org//images/Data/forweb/HRTVBSH.Metadata.pdf'
response = requests.get(url)
filename.write_bytes(response.content)

1
इसे पोस्ट करने के लिए आपका धन्यवाद। मूल प्रश्न पायथन 2.7 था, लेकिन मैं आगे बढ़ गया हूं और अब पायथन 3 का उपयोग करता हूं। मुझे पाथलीब लाइब्रेरी [संस्करण 3.4 में नया] के बारे में नहीं पता था और इसे अपनी वर्तमान परियोजनाओं में शामिल करूंगा।
जिम

यह दे 544और फ़ाइल टूट गया है, किसी भी विचार?
एहबॉन

@ हबन, आपका क्या मतलब है?
user6481870

13

आप urllib का उपयोग कर सकते हैं:

import urllib.request
urllib.request.urlretrieve(url, "filename.pdf")

यह सबसे अच्छा है, tbh।
धवल सावलिया

यह सबसे अच्छा है
रोटी

urlretrieveअनुरोध शीर्षलेखों को निर्धारित करने के लिए वैश्विक सेटिंग्स पर निर्भर करता है, जिससे यह कुछ उपयोग मामलों के लिए अनुपयुक्त हो जाता है।
माइकल क्रेंशॉ

5

आम तौर पर, यह पायथन 3 में काम करना चाहिए:

import urllib.request 
..
urllib.request.get(url)

याद रखें कि Pyllon2 के बाद urllib और urllib2 ठीक से काम नहीं करते हैं।

यदि कुछ रहस्यमय मामलों में अनुरोध काम नहीं करते (मेरे साथ हुआ), तो आप भी उपयोग करने का प्रयास कर सकते हैं

wget.download(url)

सम्बंधित:

एक वेबपेज पर सभी पीडीएफ फाइलों को खोजने और डाउनलोड करने के लिए यहां एक अच्छा स्पष्टीकरण / समाधान है:

https://medium.com/@dementorwriter/notesdownloader-use-web-scraping-to-download-all-pdfs-with-python-511ea9f55e48


2

कृपया ध्यान दें कि मैं एक शुरुआत हूँ। यदि मेरा समाधान गलत है, तो कृपया मुझे सुधार करने के लिए स्वतंत्र महसूस करें और / या मुझे बताएं। मैं कुछ नया भी सीख सकता हूं।

मेरा समाधान:

जहाँ आप चाहते हैं कि आपके फ़ाइल को सहेजा जाए, उसी के अनुसार डाउनलोडथ बदलें । अपने उपयोग के लिए भी निरपेक्ष पथ का उपयोग करने के लिए स्वतंत्र महसूस करें।

नीचे दिए गए डाउनलोड के रूप में सहेजें।

उपयोग: python downloadFile.py url-of-the-file-to-download new-file-name.extension

एक्सटेंशन जोड़ना याद रखें!

उदाहरण का उपयोग: python downloadFile.py http://www.google.co.uk google.html

import requests
import sys
import os

def downloadFile(url, fileName):
    with open(fileName, "wb") as file:
        response = requests.get(url)
        file.write(response.content)


scriptPath = sys.path[0]
downloadPath = os.path.join(scriptPath, '../Downloads/')
url = sys.argv[1]
fileName = sys.argv[2]      
print('path of the script: ' + scriptPath)
print('downloading file to: ' + downloadPath)
downloadFile(url, downloadPath + fileName)
print('file downloaded...')
print('exiting program...')

पावेल, आपके उत्तर के लिए धन्यवाद। मैं पायथन नौसिखिया था जब मैंने पहली बार इस प्रश्न को पोस्ट किया था। अब मुझे भाषा अच्छी तरह से पता है। कमांड लाइन से फाइल डाउनलोड करने के लिए पायथन स्क्रिप्ट लिखने के आपके उपयोग के मामले को उपयोगिताओं या कर्ल जैसी उपयोगिताओं द्वारा कवर किया जा सकता है। साथ ही, आपका फ़ंक्शन डाउनलोड किया गया पोस्ट के रूप में लगता है कि खुद को कॉल करता है। क्या आपने कोड के दूसरे ब्लॉक को इंडेंट करने का इरादा किया था? स्टैकओवरफ़्लो में आप उस डेंटिंग को सही कर सकते हैं। मैं आपको सुझाव देना चाहूंगा कि आप पायथन के अर्गपर्स लाइब्रेरी पर एक नज़र डालें। आप इसे अच्छी कमांड लाइन उपयोगिताओं बनाने के लिए उपयोग कर सकते हैं। यह आपके लिए मापदंडों का ध्यान रखेगा।
जिम

मैं फ़ाइल लेखन को संभालने के लिए एक संदर्भ प्रबंधक (खुले ... फ़ाइल के रूप में, आदि) के आपके उपयोग को पसंद करता हूं। आपका कोड बड़े करीने से लिखा गया है। आप पायथन सीखने के लिए एक अच्छे रास्ते पर हैं। सौभाग्य!
जिम

1
उत्तर के लिए धन्यवाद, @Jim! मैंने पोस्ट को संपादित किया है, और वास्तव में मैंने "इंडेंट करने का इरादा नहीं किया": कार्यक्रम का मुख्य हिस्सा डी। आपकी सलाह के लिए धन्यवाद! :)
डक लिंग

-5

एक फ़ोल्डर में लिखने के लिए केविन जवाब के बारे में tmp, यह इस तरह होना चाहिए:

with open('./tmp/metadata.pdf', 'wb') as f:
    f.write(response.content)

वह .पते से पहले भूल गया और निश्चित रूप से आपका फ़ोल्डर tmpपहले से ही बनाया जाना चाहिए था


5
1- केविन को लिखने का विचार नहीं आया tmp, यह ओपी के प्रश्न की तरह था। 2- /tmpडायरेक्टरी यूनिक्स सिस्टम्स में tmp है, जो कि /tmpनहीं.
realUser404
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.