Разбор html-файла и добавление найденных изображений в zip-файл

Я пытаюсь проанализировать html для всех его тегов img, загрузить все изображения, на которые указывает src, а затем добавить эти файлы в zip-файл. Я бы предпочел делать все это в памяти, так как могу гарантировать, что изображений будет не так много.

Предположим, что переменная images уже заполнена при анализе html. Мне нужна помощь, чтобы загрузить изображения в zip-файл.

from zipfile import ZipFile
from StringIO import StringIO
from urllib2 import urlopen

s = StringIO()
zip_file = ZipFile(s, 'w')
try:
    for image in images:
        internet_image = urlopen(image)
        zip_file.writestr('some-image.jpg', internet_image.fp.read())
        # it is not obvious why I have to use writestr() instead of write()
finally:
    zip_file.close()

person Jason Christa    schedule 22.12.2009    source источник
comment
используйте urllib2/lxml/xpath/google   -  person mykhal    schedule 23.12.2009
comment
Поддерживая замечания Брайана Эгнью, похоже, вы во многом разобрались. Вы должны использовать zip_file.writestr(), потому что вы пишете из буфера байтов (то есть из строки байтов), а не из файла, расположенного в файловой системе (это то, что ожидает получить zip_file.write()).   -  person Jarret Hardie    schedule 23.12.2009
comment
Не забывайте таблицу стилей и изображения, на которые она ссылается...   -  person Joachim Breitner    schedule 20.08.2013


Ответы (3)


Чтобы ответить на ваш конкретный вопрос о том, как вы создаете ZIP-архив (другие здесь обсуждали синтаксический анализ URL-адресов), я протестировал ваш код. Вы действительно очень близки к тому, чтобы иметь готовый продукт.

Вот как я бы увеличил то, что вам нужно для создания Zip-архива (в этом примере я записываю архив на диск, чтобы убедиться, что он был правильно записан).

from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED
import zlib
from cStringIO import StringIO
from urllib2 import urlopen
from urlparse import urlparse
from os import path

images = ['http://sstatic.net/so/img/logo.png', 
          'http://sstatic.net/so/Img/footer-cc-wiki-peak-internet.png']

buf = StringIO()
# By default, zip archives are not compressed... adding ZIP_DEFLATED
# to achieve that. If you don't want that, or don't have zlib on or
# system, delete the compression kwarg
zip_file = ZipFile(buf, mode='w', compression=ZIP_DEFLATED)

for image in images:
    internet_image = urlopen(image)
    fname = path.basename(urlparse(image).path) 
    zip_file.writestr(fname, internet_image.read())

zip_file.close()

output = open('images.zip', 'wb')
output.write(buf.getvalue())
output.close()
buf.close()
person Jarret Hardie    schedule 22.12.2009

Самый простой способ сделать это — использовать библиотеку BeautifulSoup.

Что-то вроде:

from BeautifulSoup import BeautifulSoup
from collections import defaultdict

def getImgSrces(html):
    srcs = []
    soup = BeautifulSoup(html)

    for tag in soup('img'):
        attrs = defaultdict(str)
        for attr in tag.attrs:
            attrs[ attr[0] ] = attr[1]
        attrs = dict(attrs)

        if 'src' in attrs.keys():
            srcs.append( attrs['src'] )

    return srcs

Это должно дать вам список URL-адресов, полученных из ваших тегов img, для циклического просмотра.

person Community    schedule 22.12.2009
comment
Почему бы просто не использовать: for attr in tag.attrs: if attr[0] == 'src': srcs.append(attr[1]) вместо этого? Зачем возиться со своим attrs словарем? - person Samir Talwar; 23.12.2009
comment
Я просто почти дословно взял пример из написанной мной подпрограммы, где мне нужен словарь всех атрибутов, хотя вы можете сделать это и таким образом. Я не уверен, что там можно много выиграть с точки зрения производительности. - person KingRadical; 23.12.2009

Я не совсем уверен, что вы здесь спрашиваете, так как вы, похоже, уже отсортировали большую часть этого.

Вы исследовали HtmlParser, чтобы фактически выполнить синтаксический анализ HTML? Я бы не стал пытаться самостоятельно создавать синтаксический анализатор - это серьезная задача с многочисленными пограничными случаями. Даже не думайте о регулярных выражениях, кроме самых тривиальных случаев.

Для каждого тега <img/> вы можете использовать HttpLib, чтобы получить каждое изображение. Возможно, стоит получить изображения в несколько потоков, чтобы ускорить компиляцию zip-файла.

person Brian Agnew    schedule 22.12.2009