parser.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #!/usr/bin/python3
  2. import threading
  3. from queue import Queue
  4. from db import db
  5. from source import Source
  6. from linklist import LinkList
  7. from news import News
  8. from paid_parser import PaidParser
  9. from time import strftime,time
  10. from multiprocessing import Pool
  11. import sys
  12. def parseSource(s):
  13. init = time()
  14. q = Queue()
  15. sel = None
  16. rss = False
  17. if "selector" in s:
  18. sel = s["selector"]
  19. if "rss" in s:
  20. rss = bool(s["rss"])
  21. l = LinkList(s["link"], sel, rss=rss)
  22. d = db()
  23. kw = d.get_keywords(s["category"])
  24. new_articles = 0
  25. # print(kw)
  26. if l is not None:
  27. for a in l.links:
  28. if not d.article_exists(a.lower(),s["_id"]):
  29. q.put(a)
  30. #print("[%s][Source] %s: %d/%d new/total articles" %
  31. # (strftime("%H:%M:%S"), s["name"], q.qsize(), len(l.links)))
  32. new_articles = q.qsize()
  33. if not q.empty():
  34. num_worker_threads = min(5, q.qsize())
  35. threads = []
  36. for i in range(num_worker_threads):
  37. t = threading.Thread(target=news_worker, args=[s, kw, d, q])
  38. t.daemon = True
  39. t.start()
  40. threads.append(t)
  41. # print("Waiting for %d queue elements" % q.qsize())
  42. q.join() # block until all tasks are done
  43. # print("Finished waiting for the queue")
  44. for i in range(num_worker_threads):
  45. q.put(None)
  46. for t in threads:
  47. t.join(10)
  48. ex_time = time()-init
  49. print("[%s][Source] %s => Finished parsing, %d/%d new articles, in %0.3fsec" %
  50. (strftime("%H:%M:%S"),
  51. s["name"], new_articles, len(l.links), ex_time)
  52. )
  53. sys.stdout.flush()
  54. #return new_articles
  55. return (ex_time, len(l.links), s["name"], new_articles)
  56. def news_worker(source, kw, d, q):
  57. source_id = source["_id"]
  58. source_name = source["name"]
  59. source_category = source["category"]
  60. paid = False
  61. if "paid" in source and source["paid"]:
  62. paid = True
  63. tname = threading.current_thread().name
  64. while True:
  65. try:
  66. item = q.get(timeout=5)
  67. except:
  68. #print("Failed to get item")
  69. q.task_done()
  70. break
  71. if item is None:
  72. q.task_done()
  73. break
  74. #print("[Thread %s] %s" % (tname,item))
  75. try:
  76. html = None
  77. if paid:
  78. p = PaidParser(item)
  79. html = p.html
  80. n = News(item, source_id, source_name,
  81. source_category, kw, html=html)
  82. #print("[Thread %s] Finished" % tname)
  83. d.insert_article(n.get())
  84. except Exception as e:
  85. print("#### EXCEPTION ########")
  86. print(e)
  87. print(item)
  88. print("#### END EXCEPTION ####")
  89. finally:
  90. q.task_done()
  91. start = time()
  92. sources = db().sources()
  93. db().purge_error()
  94. p = Pool(processes=4)
  95. ret = p.map(parseSource, sources)
  96. n = sum([ r[3] for r in ret ])
  97. tot = sum([ r[1] for r in ret ])
  98. #n = sum(ret)
  99. #sret = sorted(ret, key=lambda tup: tup[0])
  100. #print(sret)
  101. print("[%s] %d/%d new articles, total time %d sec" % (strftime("%H:%M:%S"), n, tot, time()-start))
  102. print("###############################################################################")