План был такой:
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