nightvich
@nightvich
ITman

Как ускорить скрипт Python?

Есть задача собрать с динамически обновляемой страницы собрать 100 значений.

мой г.код ))

import urllib
i=0
while i < 100:
url=urllib.urlopen('www.ya.ru')
print url.read().splitlines()
i+=1

интересна оптимизация только этой части, т.к. на ней наибольшие затраты времени.
  • Вопрос задан
  • 4394 просмотра
Пригласить эксперта
Ответы на вопрос 7
mututunus
@mututunus
Backend developer (Python, Golang)
Распараллелить запросы.
Ответ написан
Assargin
@Assargin
Перед ответом смотрю наличие ✔ в ваших вопросах
Вы, может быть, хотели бы использовать цикл в таком виде (python3):
for x in range(1, 100):  # в Py2 вроде xrange используется
    url=urllib.urlopen('www.ya.ru')
    print(url.read().splitlines())


По сути вопроса: у вас в цикле происходит http-запрос, как вы его хотите ускорить?
Эта часть вашего кода оптимизируется путем ускорения интернета + можно, если дёргаете в цикле свой сайт, оптимизировать страницу, к которой 100 раз обращаетесь.
Ответ написан
Комментировать
nightvich
@nightvich Автор вопроса
ITman
Есть рекомендация использовать ассинхронную библиотеку. Не могу понять, как это сделать. В программировании новичек...
Ответ написан
@raiboon
Grab - фреймворк для парсинга сайтов — Документация ...
https://grab.readthedocs.org/
Ответ написан
Комментировать
svfat
@svfat
☺Нужен VPS? Два месяца бесплатно. Смотри профиль☺
Можно использовать workerpool

Вот ссылка на туториал

В вашем случае код будет примерно таким:
import os
import urllib
import workerpool

urls = ['http://example.com/1','http://example.com/2']

class DownloadJob(workerpool.Job):
    def __init__(self, url):
        self.url = url # The url we'll need to download when the job runs
    def run(self):
        save_to = os.path.basename(self.url)
        urllib.urlretrieve(self.url, save_to)

pool = workerpool.WorkerPool(size=5)

for url in urls:
    job = DownloadJob(url.strip())
    pool.put(job)

pool.shutdown()
pool.wait()


Также обратите внимание на urllib3 (он более корректно и гибко работает с параллельными запросами)
Ответ написан
Комментировать
tenoclock
@tenoclock
Python/Django программист
Помогут потоки. Реализация на коленке:
# -*- coding: utf-8 -*-
from threading import Thread
import urllib2

class GetPageThread(Thread):
    def __init__(self, url):
        self.url = url
        self.body = None
        super(GetPageThread, self).__init__()
    def run(self):
        try:
            #для некоторых ресурсов доступ будет закрыт 
            #без user-agent(довольно часто)
            req = urllib2.Request(self.url, headers={'User-Agent' : 'Mozilla/5.0'})
            self.body = urllib2.urlopen(req).read()
        except:
            self.body = 'Некорректный адрес'

def body_thread(url):
    return GetPageThread(url)

def main():
    url = 'http://ya.ru'
    #создание потоков
    threads = [body_thread(url) for i in range(100)]
    #запуск потоков
    for thread in threads:
        thread.start()
    #объединение с основным
    for thread in threads:
        thread.join()
    #что хотелось бы с этим сделать
    for thread in threads:
        print thread.body.splitlines()

if __name__ == '__main__':
    main()
Ответ написан
Комментировать
dvska
@dvska
Можно использовать asyncio+aiohttp (Pyhon3.x).
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы