Уведомления

Группа в Telegram: @pythonsu

#1 Март 1, 2014 17:55:28

ajib6ept
От: От: От: От: От: От: От: От:
Зарегистрирован: 2013-08-04
Сообщения: 297
Репутация: +  26  -
Профиль   Отправить e-mail  

рефакторинг кода - парсер LI

Подскажите ошибки новичка - я написал парсер открытых статистик счетчика liveinternet.ru
План был такой:
1. Заходим на главную liveinternet.ru/rating/ и собираем все категории
2. Проходим по каждой категории и собираем количество страниц с сайтами
3. Многопоточно проходим у каждой категории по каждой странице с сайтами с собираем ссылки на “public” статистики.
4. Многопоточно проходим у каждой категории по каждой “public” статистики и отбираем те, у которых открыта ссылка “по поисковым фразам”

Полного понимания как работает асинхронный grab spider не было, поэтому отказался от такой реализации.

# -*- coding: UTF-8 -*-
import logging, threading, Queue, traceback
from grab import Grab
TH = 5
class MyClass():
    def __init__(self):
        self.urls_open_li = {}
        self.urls_open_key = {}
    def get_cat(self):
        '''
        Получаем список категорий с главной LI в список self.cat_li
        '''
        self.cat_li = []
        g = Grab()
        g.go('http://www.liveinternet.ru/rating/')
        path = ['//tr[@class="high cloud'+str(k)+'"]' for k in xrange(2,6)]
        for p in path:
            for cat in g.doc.select(p):
                self.cat_li.append(cat.select('.//td/a').attr('href')[8:].replace('/',''))
    def get_cat_url(self, cat_li=['banks']):
        '''
        Получаем количество страниц в категории.
        В словаре self.li_urls для каждой категории (ключа) сопоставляется
        список URL'ов данной категории
        '''
        self.li_urls = {}
        for c_l in cat_li:
            g = Grab()
            g.go('http://www.liveinternet.ru/rating/' + c_l + '/')
            number = int(g.doc.select('//td[@align="right"]')[1].select('.//a')[3].text())
            self.li_urls[c_l] = ['http://www.liveinternet.ru/rating/'+c_l+'/index.html?page='+str(k) for k in xrange(1,number+1)]
    
    def listmerge(self, lstlst):
        all=[]
        for lst in lstlst:
            all.extend(lst)
        return all
class LiOpenStat(threading.Thread):
    def __init__(self,queue):
        threading.Thread.__init__(self)
        self.queue = queue
        self.open_li = []
        self.open_key = []
    def run(self):
        while True:
            try: item = self.queue.get_nowait()
            except Queue.Empty: break
            try: self.worker(item)
            except Exception, detail: traceback.print_exc()
            self.queue.task_done()
    def worker(self, host):
        '''
        По каждому URL из очереди находим открытые (public) счетчики
        '''
        g = Grab()
        g.go(host)
        for site in g.doc.select('//td[@align="right"][@width="20"]//a'):
            if site.select('.//img').attr('src')[22:28] == 'public':
                self.open_li.append('http://www.liveinternet.ru' + site.attr('href'))
class LiOpenKey(LiOpenStat):
    def worker(self, host):
        '''
        У каждого public счетчика проверяем доступ по ссылке "по поисковым фразам"
        '''
        g = Grab()
        g.go(host)
        if (g.doc.select('//a[@href="queries.html"]/font').exists() is False) and (g.doc.select('//a[@href="queries.html"]').exists() is True):
            self.open_key.append(host)
def main():
    my_li = MyClass()
    my_li.get_cat()
    my_li.get_cat_url(my_li.cat_li)
    #my_li.get_cat_url(['hi-end'])
    q = Queue.Queue()
    for key in my_li.li_urls:
        all_open_li = []
        for url in my_li.li_urls[key]:
            q.put(url)
        for i in xrange(TH):
            t = LiOpenStat(q)
            t.start()
            all_open_li.append(t.open_li)
        q.join()
        my_li.urls_open_li[key] = my_li.listmerge(all_open_li)
    for key in my_li.urls_open_li:
        all_open_key = []
        for url in my_li.urls_open_li[key]:
            q.put(url)
        for i in xrange(TH):
            tt = LiOpenKey(q)
            tt.start()
            all_open_key.append(tt.open_key)
        q.join()
        my_li.urls_open_key[key] = my_li.listmerge(all_open_key)
    
    print my_li.urls_open_key
if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    main()

https://gist.github.com/ajib6ept/8901322



_________________________
Python golden rule: Do not PEP 8 unto others; only PEP 8 thy self.
Don't let PEP 8 make you insanely intolerant of other people's code.

Отредактировано ajib6ept (Март 1, 2014 17:56:51)

Офлайн

#2 Март 1, 2014 18:28:05

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

рефакторинг кода - парсер LI

Насколько я понимаю во всем вашем посте нет никакого вопроса. Собственно что вы хотите?



Отредактировано doza_and (Март 1, 2014 18:28:15)

Офлайн

#3 Март 1, 2014 18:46:31

ajib6ept
От: От: От: От: От: От: От: От:
Зарегистрирован: 2013-08-04
Сообщения: 297
Репутация: +  26  -
Профиль   Отправить e-mail  

рефакторинг кода - парсер LI

Вопрос то вот какой (неявно был задан в первом предложении) - как я понимаю, в программировании новички (такие как я) пишут код не совсем правильно, допускают стилистические ошибки, затрудняющие понимание/чтение, а более опытные товарищи подсказывают как правильно, лучше решить ту или иную задачу. Мне нужны такие подсказки.
Кто за деньги или как лучше организовать на общественных началах рефакторинг кода?



_________________________
Python golden rule: Do not PEP 8 unto others; only PEP 8 thy self.
Don't let PEP 8 make you insanely intolerant of other people's code.

Отредактировано ajib6ept (Март 1, 2014 18:47:11)

Офлайн

#4 Март 3, 2014 17:16:52

lorien
От:
Зарегистрирован: 2006-08-20
Сообщения: 755
Репутация: +  37  -
Профиль  

рефакторинг кода - парсер LI

1. Прочитайте PEP-8
2. Посмотрите на ваш код и сделайте так, чтобы он удовлетворял рекомендациям PEP-8

С первого раза вы ничего не запомните в PEP-8, так что смотрите туда постоянно на протяжении нескольких месяцев. Вот, собственно, главная рекомендация.

А ещё, давайте переменным осмысленные имена. TH, c_l - фиговые имена.

 path = ['//tr[@class="high cloud'+str(k)+'"]' for k in xrange(2,6)]
for p in path:

По-моему, проще и читаемее:
for num in xrange(2, 6):
    path = '//tr[@class="high cloud%d"]' % num
    ....

Ну и вообще используйте оператор форматирования т.е. ‘foo %d bar’ % 4, а не ‘foo ’ + str(4) + ‘ bar’

Ещё можно XPATH юзать как-то так
int(g.doc.select('//td[@align="right"]')[1].select('.//a')[3].text())
–>
int(g.doc.select('//td[@align="right"][2]//a[4]').text()

Отредактировано lorien (Март 3, 2014 17:17:53)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version