我设法让我的第一个python脚本工作,从URL下载.ZIP文件列表,然后继续提取ZIP文件并将它们写入磁盘.
我现在无法实现下一步.
我的主要目标是下载并解压缩zip文件,并通过TCP流传递内容(CSV数据).如果我能逃脱它,我宁愿不将任何zip或解压缩的文件写入磁盘.
这是我当前的脚本,但不幸的是必须将文件写入磁盘.
import urllib, urllister
import zipfile
import urllib2
import os
import time
import pickle
# check for extraction directories existence
if not os.path.isdir('downloaded'):
os.makedirs('downloaded')
if not os.path.isdir('extracted'):
os.makedirs('extracted')
# open logfile for downloaded data and save to local variable
if os.path.isfile('downloaded.pickle'):
downloadedLog = pickle.load(open('downloaded.pickle'))
else:
downloadedLog = {'key':'value'}
# remove entries older than 5 days (to maintain speed)
# path of zip files
zipFileURL = "http://www.thewebserver.com/that/contains/a/directory/of/zip/files"
# retrieve list of URLs from the webservers
usock = urllib.urlopen(zipFileURL)
parser = urllister.URLLister()
parser.feed(usock.read())
usock.close()
parser.close()
# only parse urls
for url in parser.urls:
if "PUBLIC_P5MIN" in url:
# download the file
downloadURL = zipFileURL + url
outputFilename = "downloaded/" + url
# check if file already exists on disk
if url in downloadedLog or os.path.isfile(outputFilename):
print "Skipping " + downloadURL
continue
print "Downloading ",downloadURL
response = urllib2.urlopen(downloadURL)
zippedData = response.read()
# save data to disk
print "Saving to ",outputFilename
output = open(outputFilename,'wb')
output.write(zippedData)
output.close()
# extract the data
zfobj = zipfile.ZipFile(outputFilename)
for name in zfobj.namelist():
uncompressed = zfobj.read(name)
# save uncompressed data to disk
outputFilename = "extracted/" + name
print "Saving extracted file to ",outputFilename
output = open(outputFilename,'wb')
output.write(uncompressed)
output.close()
# send data via tcp stream
# file successfully downloaded and extracted store into local log and filesystem log
downloadedLog[url] = time.time();
pickle.dump(downloadedLog, open('downloaded.pickle', "wb" ))
Run Code Online (Sandbox Code Playgroud)
Vis*_*hal 67
下面是我用来获取压缩csv文件的代码片段,请看一下:
Python 2:
from StringIO import StringIO
from zipfile import ZipFile
from urllib import urlopen
resp = urlopen("http://www.test.com/file.zip")
zipfile = ZipFile(StringIO(resp.read()))
for line in zipfile.open(file).readlines():
print line
Run Code Online (Sandbox Code Playgroud)
Python 3:
from io import BytesIO
from zipfile import ZipFile
from urllib.request import urlopen
# or: requests.get(url).content
resp = urlopen("http://www.test.com/file.zip")
zipfile = ZipFile(BytesIO(resp.read()))
for line in zipfile.open(file).readlines():
print(line.decode('utf-8'))
Run Code Online (Sandbox Code Playgroud)
这file是一个字符串.要获取要传递的实际字符串,可以使用zipfile.namelist().例如,
resp = urlopen('http://mlg.ucd.ie/files/datasets/bbc.zip')
zipfile = ZipFile(BytesIO(resp.read()))
zipfile.namelist()
# ['bbc.classes', 'bbc.docs', 'bbc.mtx', 'bbc.terms']
Run Code Online (Sandbox Code Playgroud)
sen*_*rle 54
我的建议是使用一个StringIO对象.它们模拟文件,但驻留在内存中.所以你可以这样做:
# get_zip_data() gets a zip archive containing 'foo.txt', reading 'hey, foo'
from StringIO import StringIO
zipdata = StringIO()
zipdata.write(get_zip_data())
myzipfile = zipfile.ZipFile(zipdata)
foofile = myzipfile.open('foo.txt')
print foofile.read()
# output: "hey, foo"
Run Code Online (Sandbox Code Playgroud)
或者更简单(向Vishal道歉):
myzipfile = zipfile.ZipFile(StringIO(get_zip_data()))
for name in myzipfile.namelist():
[ ... ]
Run Code Online (Sandbox Code Playgroud)
在Python 3中使用BytesIO而不是StringIO.
Zub*_*ubo 20
我想提供一个更新的Python 3版本的Vishal的优秀答案,它使用的是Python 2,以及可能已经提到过的对改编/更改的一些解释.
from io import BytesIO
from zipfile import ZipFile
import urllib.request
url = urllib.request.urlopen("http://www.unece.org/fileadmin/DAM/cefact/locode/loc162txt.zip")
with ZipFile(BytesIO(url.read())) as my_zip_file:
for contained_file in my_zip_file.namelist():
# with open(("unzipped_and_read_" + contained_file + ".file"), "wb") as output:
for line in my_zip_file.open(contained_file).readlines():
print(line)
# output.write(line)
Run Code Online (Sandbox Code Playgroud)
必要的变化:
StringIO在Python 3中没有.相反,我使用io,并从中导入BytesIO,因为我们将处理字节流 - 文档,也是这个线程.注意:
b'some text'.这是预期的,因为它们不是字符串 - 请记住,我们正在读取字节流.看看Dan04的优秀答案.我做了一些小改动:
with ... as而不是zipfile = ...根据文档.namelist()遍历zip中的所有文件并打印其内容.ZipFile对象的创建移动到with语句中,尽管我不确定这是否更好."unzipped_and_read_"到文件名的开头和".file"扩展名(我不想".txt"用于带字节串的文件).当然,如果您想使用代码缩进,则需要进行调整.
"wb"; 我有一种感觉,写二进制打开了一堆蠕虫......我没做的事:
这是一种方式:
import urllib.request
import shutil
with urllib.request.urlopen("http://www.unece.org/fileadmin/DAM/cefact/locode/2015-2_UNLOCODE_SecretariatNotes.pdf") as response, open("downloaded_file.pdf", 'w') as out_file:
shutil.copyfileobj(response, out_file)
Run Code Online (Sandbox Code Playgroud)
nin*_*cko 15
写入驻留在RAM中的临时文件
结果tempfile模块(http://docs.python.org/library/tempfile.html)就是这样的:
tempfile.SpooledTemporaryFile([max_size = 0 [,mode ='w + b'[,bufsize = -1 [,suffix =''[,prefix ='tmp'[,dir = None]]]]]])
这个函数与TemporaryFile()完全一样,除了数据在内存中假脱机,直到文件大小超过max_size,或者直到调用文件的fileno()方法为止,此时内容被写入磁盘并且操作与TemporaryFile一样进行().
生成的文件有一个额外的方法rollover(),这会导致文件无论其大小如何都会转到磁盘文件.
返回的对象是一个类文件对象,其_file属性是StringIO对象或真实文件对象,具体取决于是否已调用rollover().这个类文件对象可以在with语句中使用,就像普通文件一样.
2.6版中的新功能.
或者如果你是懒惰的并且/tmp在Linux 上安装了tmpfs ,你可以在那里创建一个文件,但你必须自己删除它并处理命名
lab*_*idi 14
我想为完整性添加我的Python3答案:
from io import BytesIO
from zipfile import ZipFile
import requests
def get_zip(file_url):
url = requests.get(file_url)
zipfile = ZipFile(BytesIO(url.content))
zip_names = zipfile.namelist()
if len(zip_names) == 1:
file_name = zip_names.pop()
extracted_file = zipfile.open(file_name)
return extracted_file
return [zipfile.open(file_name) for file_name in zip_names]
Run Code Online (Sandbox Code Playgroud)
小智 12
使用请求添加其他答案:
# download from web
import requests
url = 'http://mlg.ucd.ie/files/datasets/bbc.zip'
content = requests.get(url)
# unzip the content
from io import BytesIO
from zipfile import ZipFile
f = ZipFile(BytesIO(content.content))
print(f.namelist())
# outputs ['bbc.classes', 'bbc.docs', 'bbc.mtx', 'bbc.terms']
Run Code Online (Sandbox Code Playgroud)
使用help(f)获取更多函数详细信息,例如extractall(),它提取zip文件中的内容,以后可以与open一起使用.
所有这些答案都显得过于庞大和冗长。使用requests来缩短代码,例如:
import requests, zipfile, io
r = requests.get(zip_file_url)
z = zipfile.ZipFile(io.BytesIO(r.content))
z.extractall("/path/to/directory")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
75788 次 |
| 最近记录: |