Найти - Пользователи
Полная версия: рефакторинг кода - парсер LI
Начало » Python для новичков » рефакторинг кода - парсер LI
1
ajib6ept
Подскажите ошибки новичка - я написал парсер открытых статистик счетчика 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
doza_and
Насколько я понимаю во всем вашем посте нет никакого вопроса. Собственно что вы хотите?
ajib6ept
Вопрос то вот какой (неявно был задан в первом предложении) - как я понимаю, в программировании новички (такие как я) пишут код не совсем правильно, допускают стилистические ошибки, затрудняющие понимание/чтение, а более опытные товарищи подсказывают как правильно, лучше решить ту или иную задачу. Мне нужны такие подсказки.
Кто за деньги или как лучше организовать на общественных началах рефакторинг кода?
lorien
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()
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB