اینم یه تجربه پراکنده دیگه!
بسیار پیش میاد که بازار بعضی چیزها توی مملکتما بصورت ناگهانی داغ بشه و باز سرد بشه. این جو ایجاد شده بعضی وقتها خوب و بعضی وقتها بده و بعضی وقتها دامن من رو هم میگیره. حدودا یک سال پیش تب درست کردن سایتی که خبر جمع کنه و اخبار رو بصورت اتوماتیک دسته بندی کنه داغ بود. بصورت قارچی سرویسهایی که اخبار رو جمع آوری میکردن سر از خاک در آوردن و موفق شدن یا شکست خوردن. در این حین من به این نتیجه رسیدم که خوبه که من هم به عنوان یه موضوع جانبی و سرگرمی این کار رو انجام بدم. یکی از مشکلاتی که توی این کار داشتم این بود که دسته بندی درست مطالب تاثیر بسیار زیادی توی احتمال رسیدن افراد به این سایت داره. اما مهمترین چیزی که نبود این بود که لیست کلمات کلیدی فارسی اونم تو حوزه تکنولوژی نبود. پس من تصمیم گرفتم به کمک وب این لیست رو بوجود بیارم
اون موقع تازه نارنجی رو تعطیل کرده بودند اما هنوز سایت سرجاش بود. به علت کیفیت خوب کار دوستان توی نارنجی هم تگهایی که به مطالب داده بودن به عنوان لیست کلمات کلیدی قابل اعتماد بود. پس من به این نتیجه رسیدم که یه سری اسکریپت بنویسم که این کلمات رو استخراج کنم. یکم توی اینترنت گشتم و ابزارهای مربوط به استخراج اطلاعات از صفحات وب(web scraping) رو بررسی کردم. آخرش به این نتیجه رسیدم که پایتون و beautiful soup رو پیدا کردم و به کمک اون اسکریپ رو نوشتم.
خب اول از همه تابع استخراج تمامی url های تمام پستهای نارنجی هست
def getNarenjiURLs(inUrl): lst = [] url = 'http://narenji.ir/' # Check if it is a valid URL if 'http://' in inUrl: url = inUrl else: url = 'http://' + inUrl # logging start time rst = time.time() # getting URL content r = requests.get(url) #logging end time rend = time.time() pst = time.time() data = r.text # parsing content using Beautiful soupe soup = BeautifulSoup(data, 'lxml') for link in soup.find_all('div',class_='views-field views-field-title'): for a in link.find_all('a'): if a['href'].startswith('/'): lst.append('http://narenji.ir' + a['href']) else : lst.append(a['href']) pend = time.time() #print (' r Time = ' + str(rend - rst) +' p Time ' + str(pend - pst)) return lst
خب بعدش نوبت میرسه به اینکه توی هر صفحه کلمات کلیدی رو استخراج کنم. با بررسی سورس html سایت متوجه شدم که تمام کلمات کلیدی یه الگوی خاص دارن و اون الگو قابل استخراج بود. کد این کار هم در پایین اومده
def getNarenjiKeywords(inUrl): lst = [] url = "" if 'http://' in inUrl: url = inUrl else: url = 'http://' + inUrl # logging start time rst = time.time() # getting URL content r = requests.get(url) #logging end time rend = time.time() pst = time.time() # parsing content using Beautiful data = r.text soup = BeautifulSoup(data, 'lxml') for link in soup.find('div',class_='meta').findAll('a'): lst.append(link.text) pend = time.time() #print (' r Time = ' + str(rend - rst) +' p Time = ' + str(pend - pst)) return lst
با توجه به بررسیهایی که انجام دادم متوجه شدم اگه این کار رو بخوام بصورت متوالی انجام بدم کلی طول خواهد کشید پس تلاش کردم که کار رو بصورت موازی انجام بدم. پس به ازای هر درخواست یه Thread بالا آوردم و بصورت موازی این کارها رو انجام دادم. یه کد warpper رو این دوتا تابع بصورت زیر نوشتم.
def doUrlWork(): global urlList while True: url=qGetUrl.get() tmpUrl = getNarenjiURLs(url) print ( str(len(tmpUrl)) + ' URLs found') urlList.update(set(tmpUrl)) qGetUrl.task_done() def doKeywordWork(): global keys while True: url=qGetKeywords.get() tmpKey = getNarenjiKeywords(url) print ( str(len(tmpKey)) + ' keys found') keys.update(set(tmpKey)) qGetKeywords.task_done()
برای اینکه تعداد Thread ها زیاد نشه از یه صف استفاده کردم که الان یادم نیست. همچنین از مجموعههای پایتون برای حذف کلمات تکراری استفاده کردم.
پس اگه بخوام کل اسکریپت بصورت یکجا بیارم میشه:
import timeit import time from bs4 import BeautifulSoup import urllib2 import requests from Queue import Queue from threading import Thread import codecs keys = set([]) urlList = set([]) concurrent = 10 def doUrlWork(): global urlList while True: url=qGetUrl.get() tmpUrl = getNarenjiURLs(url) print ( str(len(tmpUrl)) + ' URLs found') urlList.update(set(tmpUrl)) qGetUrl.task_done() def doKeywordWork(): global keys while True: url=qGetKeywords.get() tmpKey = getNarenjiKeywords(url) print ( str(len(tmpKey)) + ' keys found') keys.update(set(tmpKey)) qGetKeywords.task_done() def getNarenjiKeywords(inUrl): lst = [] url = "" if 'http://' in inUrl: url = inUrl else: url = 'http://' + inUrl # logging start time rst = time.time() # getting URL content r = requests.get(url) #logging end time rend = time.time() pst = time.time() # parsing content using Beautiful data = r.text soup = BeautifulSoup(data, 'lxml') for link in soup.find('div',class_='meta').findAll('a'): lst.append(link.text) pend = time.time() #print (' r Time = ' + str(rend - rst) +' p Time = ' + str(pend - pst))
به این ترتیب کلمات کلیدی نارنجی بصورت موازی استخراج شد و ذخیره شد!
همین!