Guest User

OCW PS5 solution

a guest
Aug 13th, 2013
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.13 KB | None | 0 0
  1. # 6.00 Problem Set 5
  2. # RSS Feed Filter
  3. # Name: SOLUTIONS
  4. # Collaborators:
  5. # Time:
  6.  
  7. import feedparser
  8. import string
  9. import time
  10. from project_util import translate_html
  11. from news_gui import Popup
  12.  
  13. #-----------------------------------------------------------------------
  14. #
  15. # Problem Set 5
  16.  
  17. #======================
  18. # Code for retrieving and parsing
  19. # Google and Yahoo News feeds
  20. # Do not change this code
  21. #======================
  22.  
  23. def process(url):
  24.     """
  25.    Fetches news items from the rss url and parses them.
  26.    Returns a list of NewsStory-s.
  27.    """
  28.     feed = feedparser.parse(url)
  29.     entries = feed.entries
  30.     ret = []
  31.     for entry in entries:
  32.         guid = entry.guid
  33.         title = translate_html(entry.title)
  34.         link = entry.link
  35.         summary = translate_html(entry.summary)
  36.         try:
  37.             subject = translate_html(entry.tags[0]['term'])
  38.         except AttributeError:
  39.             subject = ""
  40.         newsStory = NewsStory(guid, title, subject, summary, link)
  41.         ret.append(newsStory)
  42.     return ret
  43.  
  44. #======================
  45. # Part 1
  46. # Data structure design
  47. #======================
  48.  
  49. # Problem 1
  50.  
  51. # TODO: NewsStory
  52. class NewsStory(object):
  53.     def __init__(self, guid, title, subject, summary, link):
  54.         self.guid = guid
  55.         self.title = title
  56.         self.subject = subject
  57.         self.summary = summary
  58.         self.link = link
  59.  
  60.     def get_guid(self):
  61.         return self.guid
  62.  
  63.     def get_title(self):
  64.         return self.title
  65.  
  66.     def get_subject(self):
  67.         return self.subject
  68.  
  69.     def get_summary(self):
  70.         return self.summary
  71.  
  72.     def get_link(self):
  73.         return self.link
  74.  
  75. #======================
  76. # Part 2
  77. # Triggers
  78. #======================
  79.  
  80. class Trigger(object):
  81.     def evaluate(self, story):
  82.         """
  83.        Returns True if an alert should be generated
  84.        for the given news item, or False otherwise.
  85.        """
  86.         raise NotImplementedError
  87.  
  88. # Whole Word Triggers
  89. # Problems 2-5
  90.  
  91. # TODO: WordTrigger
  92. class WordTrigger(Trigger):
  93.     def __init__(self, word):
  94.         self.word = word
  95.  
  96.     def is_word_in(self, text):
  97.         word = self.word.lower()
  98.         text = text.lower()
  99.  
  100.         # Remove punctation and split the text
  101.         for punc in string.punctuation:
  102.             text = text.replace(punc, " ")
  103.         splittext = text.split(" ")
  104.  
  105.         # Check if the word is in the text
  106.         return word in splittext
  107.  
  108. ### TODO: TitleTrigger
  109. ##class TitleTrigger(WordTrigger): -- alternative
  110. ##    def __init__(self, word):
  111. ##        self.word = word
  112. ##
  113. ##    def evaluate(self, story):
  114. ##        return self.is_word_in(story.get_title())
  115.  
  116. # TODO: TitleTrigger
  117. class TitleTrigger(WordTrigger):
  118. ##    def __init__(self, word):
  119. ##        WordTrigger.__init__(self, word)
  120.  
  121.     def evaluate(self, story):
  122.         return self.is_word_in(story.get_title())
  123.    
  124. # TODO: SubjectTrigger
  125. class SubjectTrigger(WordTrigger):
  126.     def __init__(self, word):
  127.         WordTrigger.__init__(self, word)
  128.  
  129.     def evaluate(self, story):
  130.         return self.is_word_in(story.get_subject())
  131.    
  132. # TODO: SummaryTrigger
  133. class SummaryTrigger(WordTrigger):
  134.     def __init__(self, word):
  135.         WordTrigger.__init__(self, word)
  136.  
  137.     def evaluate(self, story):
  138.         return self.is_word_in(story.get_summary())
  139.  
  140. # Composite Triggers
  141. # Problems 6-8
  142.  
  143. # TODO: NotTrigger
  144. class NotTrigger(Trigger):
  145.     def __init__(self, trigger):
  146.         self.t = trigger
  147.  
  148.     def evaluate(self, story):
  149.         return not self.t.evaluate(story)
  150.    
  151. # TODO: AndTrigger
  152. class AndTrigger(Trigger):
  153.     def __init__(self, trigger1, trigger2):
  154.         self.t1 = trigger1
  155.         self.t2 = trigger2
  156.  
  157.     def evaluate(self, story):
  158.         return self.t1.evaluate(story) and self.t2.evaluate(story)
  159.    
  160. # TODO: OrTrigger
  161. class OrTrigger(Trigger):
  162.     def __init__(self, trigger1, trigger2):
  163.         self.t1 = trigger1
  164.         self.t2 = trigger2
  165.  
  166.     def evaluate(self, story):
  167.         return self.t1.evaluate(story) or self.t2.evaluate(story)
  168.  
  169. # Phrase Trigger
  170. # Question 9
  171.  
  172. # TODO: PhraseTrigger
  173. class PhraseTrigger(Trigger):
  174.     def __init__(self, phrase):
  175.         self.phrase = phrase
  176.  
  177.     def evaluate(self, story):
  178.         return self.phrase in story.get_title() or \
  179.                self.phrase in story.get_summary() or \
  180.                self.phrase in story.get_subject()
  181.  
  182.  
  183. #======================
  184. # Part 3
  185. # Filtering
  186. #======================
  187.  
  188. def filter_stories(stories, triggerlist):
  189.     """
  190.    Takes in a list of NewsStory-s.
  191.    Returns only those stories for whom
  192.    a trigger in triggerlist fires.
  193.    """
  194.     # TODO: Problem 10
  195.     # This is a placeholder (we're just returning all the stories, with no filtering)
  196.     # Feel free to change this line!
  197. ##  return stories
  198.     res = []
  199.     for story in stories:
  200.         for trigger in triggerlist:
  201.             if trigger.evaluate(story):
  202.                 res.append(story)
  203.                 break
  204.     return res
  205.  
  206. #======================
  207. # Part 4
  208. # User-Specified Triggers
  209. #======================
  210.  
  211. def makeTrigger(trigger_map, trigger_type, params, name):
  212.     """
  213.    Takes in a map of names to trigger instance, the type of trigger to make,
  214.    and the list of parameters to the constructor, and returns a new
  215.    trigger instance.
  216.  
  217.    trigger_map: dictionary with names as keys (strings) and triggers as values
  218.    trigger_type: string indicating the type of trigger to make (ex: "TITLE", "AND")
  219.    params: list of strings with the inputs to the trigger constructor (ex: ["world"], ["t2", "t3"])
  220.    name: a string representing the name of the new trigger (ex: "t1", "t2")
  221.  
  222.    Returns a new instance of a trigger (ex: TitleTrigger, AndTrigger).
  223.  
  224.    Modifies trigger_map, adding a new key-value pair for this trigger.
  225.    """
  226.     if trigger_type == "TITLE":
  227.         trigger = TitleTrigger(params[0])
  228.  
  229.     elif trigger_type == "SUBJECT":
  230.         trigger = SubjectTrigger(params[0])
  231.  
  232.     elif trigger_type == "SUMMARY":
  233.         trigger = SummaryTrigger(params[0])
  234.  
  235.     elif trigger_type == "NOT":
  236.         trigger = NotTrigger(trigger_map[params[0]])
  237.  
  238.     elif trigger_type == "AND":
  239.         trigger = AndTrigger(trigger_map[params[0]], trigger_map[params[1]])
  240.  
  241.     elif trigger_type == "OR":
  242.         trigger = OrTrigger(trigger_map[params[0]], trigger_map[params[1]])
  243.  
  244.     elif trigger_type == "PHRASE":
  245.         trigger = PhraseTrigger(" ".join(params))
  246.  
  247.     else:
  248.         return None
  249.  
  250.     trigger_map[name] = trigger
  251.  
  252. def readTriggerConfig(filename):
  253.     """
  254.    Returns a list of trigger objects
  255.    that correspond to the rules set
  256.    in the file filename
  257.    """
  258.     # Here's some code that we give you
  259.     # to read in the file and eliminate
  260.     # blank lines and comments
  261.     triggerfile = open(filename, "r")
  262.     all = [ line.rstrip() for line in triggerfile.readlines() ]
  263.     lines = []
  264.     for line in all:
  265.         if len(line) == 0 or line[0] == '#':
  266.             continue
  267.         lines.append(line)
  268.  
  269.     # TODO: Problem 11
  270.     # 'lines' has a list of lines you need to parse
  271.     # Build a set of triggers from it and
  272.     # return the appropriate ones
  273.     triggers = []
  274.     trigger_map = {}
  275.     for line in lines:
  276.  
  277.         linesplit = line.split(" ")
  278.  
  279.         # Making a new trigger
  280.         if linesplit[0] != "ADD":
  281.             trigger = makeTrigger(trigger_map, linesplit[1],
  282.                                   linesplit[2:], linesplit[0])
  283.  
  284.         # Add the triggers to the list
  285.         else:
  286.             for name in linesplit[1:]:
  287.                 triggers.append(trigger_map[name])
  288.  
  289.     return triggers
  290.        
  291.    
  292. import thread
  293.  
  294. def main_thread(p):
  295.     # A sample trigger list - you'll replace
  296.     # this with something more configurable in Problem 11
  297.     t1 = SummaryTrigger("Romney")
  298.     t2 = SubjectTrigger("Iran")
  299.     t3 = PhraseTrigger("Wall Street")
  300.     t4 = OrTrigger(t2, t3)
  301.     triggerlist = [t1, t4]
  302.    
  303.     # TODO: Problem 11
  304.     # After implementing readTriggerConfig, uncomment this line
  305.     triggerlist = readTriggerConfig("triggers.txt")
  306.  
  307.     guidShown = []
  308.    
  309.     while True:
  310.         print "Polling . . .",
  311.  
  312.         # Get stories from Google's Top Stories RSS news feed
  313.         stories = process("http://news.google.com/?output=rss")
  314.         # Get stories from Yahoo's Top Stories RSS news feed
  315.         stories.extend(process("http://rss.news.yahoo.com/rss/topstories"))
  316.  
  317.         # Only select stories we're interested in
  318.         stories = filter_stories(stories, triggerlist)
  319.    
  320.         # Don't print a story if we have already printed it before
  321.         newstories = []
  322.         for story in stories:
  323.             print ". . .",
  324.             if story.get_guid() not in guidShown:
  325.                 newstories.append(story)
  326.         print ". . ."
  327.         for story in newstories:
  328.             guidShown.append(story.get_guid())
  329.             p.newWindow(story)
  330.  
  331.         print "Sleeping..."
  332.         time.sleep(SLEEPTIME)
  333.  
  334. SLEEPTIME = 60 #seconds -- how often we poll
  335. if __name__ == '__main__':
  336.     p = Popup()
  337.     thread.start_new_thread(main_thread, (p,))
  338.     p.start()
Advertisement
Add Comment
Please, Sign In to add comment