سؤال

إذا كنت فتح ملف باستخدام urllib2، كما يلي:

remotefile = urllib2.urlopen('http://example.com/somefile.zip')

هل هناك طريقة سهلة للحصول على اسم ملف آخر ثم تحليل URL الأصلي؟

وتحرير: تغير openfile إلى urlopen ... لا يدري كيف حدث ذلك

وEDIT2: انتهى بي الأمر باستخدام:

filename = url.split('/')[-1].split('#')[0].split('?')[0]

واذا لم اكن مخطئا، وهذا ينبغي تجريد من جميع الاستفسارات المحتملة كذلك.

نصائح أخرى

إذا كنت تريد فقط اسم الملف نفسه، على افتراض أنه لا يوجد المتغيرات الاستعلام في نهاية مثل <وأ href = "http://example.com/somedir/somefile.zip؟foo=bar" يختلط = "noreferrer" > http://example.com/somedir/somefile.zip؟foo=bar ثم يمكنك استخدام os.path.basename لذلك:

[user@host]$ python
Python 2.5.1 (r251:54869, Apr 18 2007, 22:08:04) 
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.path.basename("http://example.com/somefile.zip")
'somefile.zip'
>>> os.path.basename("http://example.com/somedir/somefile.zip")
'somefile.zip'
>>> os.path.basename("http://example.com/somedir/somefile.zip?foo=bar")
'somefile.zip?foo=bar'

وبعض غيرها من الملصقات المذكورة باستخدام urlparse، التي ستعمل، ولكن كنت لا تزال بحاجة إلى تجريد دليل أولي من اسم الملف. إذا كنت تستخدم os.path.basename () ثم لم يكن لديك ما يدعو للقلق بشأن ذلك، لأنه يعود فقط الجزء الأخير من مسار URL أو الملف.

وأعتقد أن "اسم الملف" ليس مفهوما جدا واضحة المعالم عندما يتعلق الأمر إلى http النقل. قد (ولكن غير مطلوب ل) خادم تقديم واحدة باسم "المحتوى التصرف" رأس، يمكنك محاولة للحصول على هذا مع remotefile.headers['Content-Disposition']. وإذا فشل ذلك، ربما لديك تحليل URI نفسك.

وفقط رأيت هذا أفعله عادة ..

filename = url.split("?")[0].split("/")[-1]

وعن طريق urlsplit هو الخيار الأكثر أمانا:

url = 'http://example.com/somefile.zip'
urlparse.urlsplit(url).path.split('/')[-1]

هل يعني urllib2.urlopen؟ ليس هناك وظيفة تسمى openfile في وحدة urllib2.

وعلى أي حال، استخدام وظائف urllib2.urlparse:

>>> from urllib2 import urlparse
>>> print urlparse.urlsplit('http://example.com/somefile.zip')
('http', 'example.com', '/somefile.zip', '', '')

وفويلا.

ويمكن أيضا الجمع بين اثنين من الإجابات أفضل تصنيف: باستخدام urllib2.urlparse.urlsplit () للحصول على جزء مسار URL، ثم os.path.basename لاسم الملف الفعلي.

ورمز كامل ستكون كما يلي:

>>> remotefile=urllib2.urlopen(url)
>>> try:
>>>   filename=remotefile.info()['Content-Disposition']
>>> except KeyError:
>>>   filename=os.path.basename(urllib2.urlparse.urlsplit(url).path)

وظيفة os.path.basename تعمل ليس فقط لمسارات الملفات، ولكن أيضا لعناوين المواقع، لذلك لم يكن لديك لتحليل URL يدويا نفسك. أيضا، من المهم أن نلاحظ أنه يجب استخدام result.url بدلا من عنوان الموقع الأصلي من أجل متابعة إعادة توجيه الردود:

import os
import urllib2
result = urllib2.urlopen(url)
real_url = urllib2.urlparse.urlparse(result.url)
filename = os.path.basename(real_url.path)

وأعتقد أن ذلك يعتمد على ما تعنيه تحليل. لا توجد وسيلة للحصول على اسم الملف بدون تحليل URL، أي لا الملقم البعيد تعطيك اسم الملف. ومع ذلك، لم يكن لديك لتفعل الكثير بنفسك، هناك وحدة urlparse:

In [9]: urlparse.urlparse('http://example.com/somefile.zip')
Out[9]: ('http', 'example.com', '/somefile.zip', '', '', '')

وليس أن أعرف.

ولكن يمكنك تحليل من السهل بما فيه الكفاية مثل هذا:

و

url = 'http://example.com/somefile.zip'
print url.split('/')[-1]

وباستخدام الطلبات، ولكن يمكنك أن تفعل ذلك بسهولة مع urllib (2)

import requests
from urllib import unquote
from urlparse import urlparse

sample = requests.get(url)

if sample.status_code == 200:
    #has_key not work here, and this help avoid problem with names

    if filename == False:

        if 'content-disposition' in sample.headers.keys():
            filename = sample.headers['content-disposition'].split('filename=')[-1].replace('"','').replace(';','')

        else:

            filename = urlparse(sample.url).query.split('/')[-1].split('=')[-1].split('&')[-1]

            if not filename:

                if url.split('/')[-1] != '':
                    filename = sample.url.split('/')[-1].split('=')[-1].split('&')[-1]
                    filename = unquote(filename)

وربما يمكنك استخدام تعبير عادي بسيط هنا. شيء من هذا القبيل:

In [26]: import re
In [27]: pat = re.compile('.+[\/\?#=]([\w-]+\.[\w-]+(?:\.[\w-]+)?$)')
In [28]: test_set 

['http://www.google.com/a341.tar.gz',
 'http://www.google.com/a341.gz',
 'http://www.google.com/asdasd/aadssd.gz',
 'http://www.google.com/asdasd?aadssd.gz',
 'http://www.google.com/asdasd#blah.gz',
 'http://www.google.com/asdasd?filename=xxxbl.gz']

In [30]: for url in test_set:
   ....:     match = pat.match(url)
   ....:     if match and match.groups():
   ....:         print(match.groups()[0])
   ....:         

a341.tar.gz
a341.gz
aadssd.gz
aadssd.gz
blah.gz
xxxbl.gz

PurePosixPath التي لا تعمل تعتمد على نظام و يعالج عناوين برشاقة هو الحل pythonic:

>>> from pathlib import PurePosixPath
>>> path = PurePosixPath('http://example.com/somefile.zip')
>>> path.name
'somefile.zip'
>>> path = PurePosixPath('http://example.com/nested/somefile.zip')
>>> path.name
'somefile.zip'

لاحظ كيف لا يوجد أي حركة مرور الشبكة هنا أو أي شيء (أي تلك عناوين لا تذهب إلى أي مكان) - مجرد استخدام قواعد الاعراب القياسية

import os,urllib2
resp = urllib2.urlopen('http://www.example.com/index.html')
my_url = resp.geturl()

os.path.split(my_url)[1]

# 'index.html'

وهذا ليس openfile، ولكن ربما لا يزال يساعد:)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top