Загрузить изображения с веб-страницы - PullRequest
1 голос
/ 09 апреля 2011

Я хочу реализовать функцию, подобную этой http://www.tineye.com/parse?url=yahoo.com - разрешить пользователю загружать изображения с любой веб-страницы.

Основная проблема для меня заключается в том, что веб-страницам с большим количеством изображений требуется слишком много времени.

Я делаю это в Django (используя curl или urllib) по следующей схеме:

  1. Захватить html страницы (для больших страниц требуется около 1 секунды):

    file = urllib.urlopen(requested_url)
    html_string = file.read()
    
  2. Синтаксический анализ HTML-парсера (BeautifulSoup), поиск тегов img и запись всех изображений в список. (для больших страниц занимает около 1 секунды)

  3. Проверьте размеры всех изображений в моем списке и, если они достаточно велики, верните их в ответ json (занимает очень много времени около 15 секунд, когда на веб-странице около 80 изображений). Вот код функции:


 def get_image_size(uri):
    file = urllib.urlopen(uri)
    p = ImageFile.Parser()
    data = file.read(1024)
    if not data:
        return None
    p.feed(data)
    if p.image:
        return p.image.size
    file.close()
    #not an image
    return None

Как видите, я не загружаю полное изображение, чтобы получить его размер, только 1 КБ. Но это все еще занимает слишком много времени, когда есть много изображений (я вызываю эту функцию один раз для каждого найденного изображения).

Так как я могу заставить его работать быстрее?

Может быть, есть ли способ не делать запрос на каждое изображение?

Любая помощь будет высоко оценена.

Спасибо!

Ответы [ 2 ]

1 голос
/ 10 апреля 2011

Я могу подумать о нескольких оптимизациях:

  1. разбирать, когда вы читаете файл из потока
  2. использовать SAX-парсер (что будет хорошо с точкой выше)
  3. используйте HEAD для получения размера изображений
  4. используйте очередь для размещения изображений, затем используйте несколько потоков для подключения и получения размеров файлов

пример запроса HEAD:

$ telnet m.onet.pl 80
Trying 213.180.150.45...
Connected to m.onet.pl.
Escape character is '^]'.
HEAD /_m/33fb7563935e11c0cba62f504d91675f,59,29,134-68-525-303-0.jpg HTTP/1.1
host: m.onet.pl

HTTP/1.0 200 OK
Server: nginx/0.8.53
Date: Sat, 09 Apr 2011 18:32:44 GMT
Content-Type: image/jpeg
Content-Length: 37545
Last-Modified: Sat, 09 Apr 2011 18:29:22 GMT
Expires: Sat, 16 Apr 2011 18:32:44 GMT
Cache-Control: max-age=604800
Accept-Ranges: bytes
Age: 6575
X-Cache: HIT from emka1.m10r2.onet
Via: 1.1 emka1.m10r2.onet:80 (squid)
Connection: close

Connection closed by foreign host.
1 голос
/ 10 апреля 2011

Вы можете использовать атрибут headers файла как объект, возвращаемый urllib2.urlopen (я не знаю о urllib).

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

|milo|laurie|¥ cat test.py
import urllib2
uri = "http://download.thinkbroadband.com/1GB.zip"

def get_file_size(uri):
    file = urllib2.urlopen(uri)
    content_header, = [header for header in file.headers.headers if header.startswith("Content-Length")]
    _, str_length = content_header.split(':')
    length = int(str_length.strip())
    return length

if __name__ == "__main__":
    get_file_size(uri)
|milo|laurie|¥ time python2 test.py
python2 test.py  0.06s user 0.01s system 35% cpu 0.196 total
...