root/TwitterIrcGateway/trunk/TwitterIrcGatewayCore/AddIns/DLRIntegration/Samples/scraping.py @ 675

Revision 675, 6.0 kB (checked in by tomoyo, 10 months ago)

HTMLの変更に対して修正。

Line 
1import sys
2import clr
3import re
4import thread
5import time
6
7import Misuzilla.Applications.TwitterIrcGateway
8import Misuzilla.Applications.TwitterIrcGateway.AddIns
9import Misuzilla.Applications.TwitterIrcGateway.AddIns.Console
10
11from System import *
12from System.Threading import Thread, ThreadStart
13from System.Collections.Generic import *
14from System.Diagnostics import Trace
15from Misuzilla.Applications.TwitterIrcGateway import Status, Statuses, User, Users, Utility
16from Misuzilla.Applications.TwitterIrcGateway.AddIns import IConfiguration, ConfigurationPropertyInfo
17from Misuzilla.Applications.TwitterIrcGateway.AddIns.Console import ConsoleAddIn, Console, Context
18from Misuzilla.Applications.TwitterIrcGateway.AddIns.DLRIntegration import DLRIntegrationAddIn, DLRBasicConfiguration, DLRContextHelper
19
20class ScrapingContext(Context):
21        def Initialize(self):
22                self.scraping = Scraping.instance()
23                self.config = self.scraping.config
24                pass
25
26        def GetCommands(self):
27                dict = Context.GetCommands(self)
28                dict["Interval"] = "取得間隔を設定します。"
29                dict["Relogin"] = "再ログインします。"
30                dict["Enable"] = "スクレイピングを有効にします。"
31                dict["Disable"] = "スクレイピングを無効にします。"
32                return dict
33
34        def OnUninitialize(self):
35                pass
36
37        def get_Configurations(self):
38                return Array[IConfiguration]([ self.config ])
39
40        # Implementation
41        def Interval(self, args):
42                if String.IsNullOrEmpty(args):
43                        self.Console.NotifyMessage("取得間隔を指定してください。")
44                        return
45                interval = int(args, 10)
46                self.scraping.interval = interval
47                self.config.SetValue("Interval", interval)
48                self.Console.NotifyMessage("取得間隔を %s 秒に設定しました。" % args)
49                self.scraping.start()
50
51        def Relogin(self, args):
52                self.Console.NotifyMessage("ログインしています...")
53                CurrentSession.TwitterService.CookieLogin()
54                self.Console.NotifyMessage("ログインしました。")
55
56        def Enable(self, args):
57                self.config.SetValue("Enable", True)
58                self.scraping.enable = True
59                self.scraping.start()
60                self.Console.NotifyMessage("スクレイピングを有効にしました")
61
62        def Disable(self, args):
63                self.config.SetValue("Enable", False)
64                self.scraping.enable = False
65                self.Console.NotifyMessage("スクレイピングを無効にしました")
66
67class Scraping(Object):
68        @classmethod
69        def instance(klass):
70                if not hasattr(klass, 'instance_'):
71                        klass.instance_ = Scraping()
72                return klass.instance_
73
74        def __init__(self):
75                # 普通の #Console にコンテキストを追加する
76                CurrentSession.AddInManager.GetAddIn[ConsoleAddIn]().RegisterContext(DLRContextHelper.Wrap(CurrentSession, "ScrapingContext", ScrapingContext), "Scraping", "スクレイピングの設定を行うコンテキストに切り替えます")
77                CurrentSession.AddInManager.GetAddIn[DLRIntegrationAddIn]().BeforeUnload += self.onBeforeUnload
78                CurrentSession.PostProcessTimelineStatuses += self.onPostProcessTimelineStatuses
79                self.running = False
80                self.thread = None
81               
82                self.config = DLRBasicConfiguration(CurrentSession, "ScrapingContext", Array[ConfigurationPropertyInfo]([ConfigurationPropertyInfo("Enable", "スクレイピングを利用するかどうか", Boolean, False, None), ConfigurationPropertyInfo("Interval", "取得間隔", Int32, 30, None), ConfigurationPropertyInfo("DisableTimelineApi", "APIによるタイムライン取得を停止するかどうか", Boolean, False, None)]))
83
84                self.interval = self.config.GetValue("Interval")
85                self.enable = self.config.GetValue("Enable")
86
87                self.re_source = re.compile(r"<span>from (.*?)</span>")
88                self.re_statuses = re.compile(r"<li class=\"hentry u-.*? status.*?</li>", re.S)
89                self.re_content = re.compile(r"class=\"entry-content\">(.*?)</span>")
90                self.re_user = re.compile(r"class=\"screen-name\" title=\"([^\"]+)\">(.*?)</a>")
91                self.re_anchor = re.compile(r"<a href=\"(http://[^\"]*)\"[^>]*>.*?</a>")
92                self.re_tag = re.compile(r"<[^>]*>")
93                self.re_status_id = re.compile(r"id=\"status_(\d+)\"")
94
95        def start(self):
96                if not self.running:
97                        try:
98                                CurrentSession.TwitterService.CookieLogin()
99                        except:
100                                pass
101                        self.thread = Thread(ThreadStart(self.runProc))
102                        self.thread.Start()
103
104        def runProc(self):
105                self.running = True
106                while self.interval > 0 and self.enable:
107                        try:
108                                self.fetchHome()
109                        except:
110                                Trace.WriteLine(sys.exc_info().ToString())
111                        Thread.Sleep(self.interval * 1000)
112                self.running = False
113
114        def fetchHome(self):
115                home = CurrentSession.TwitterService.GETWithCookie("/home")
116                statuses = self.re_statuses.findall(home)
117                statuses.reverse()
118                for status in statuses:
119                        s = Status()
120                        # User
121                        match = self.re_user.search(status)
122                        s.User            = User()
123                        s.User.Id         = 0
124                        s.User.Name       = match.group(1)
125                        s.User.ScreenName = match.group(2)
126                       
127                        # Status
128                        s.Source    = self.re_source.search(status).group(1)
129                        s.Text      = Utility.UnescapeCharReference(self.re_tag.sub(r"", self.re_anchor.sub(r"\1", self.re_content.search(status).group(1))))
130                        s.Id        = int(self.re_status_id.search(status).group(1), 10)
131                        s.CreatedAt = DateTime.Now
132                       
133                        #Trace.WriteLine(s.ToString())
134                        CurrentSession.TwitterService.ProcessStatus(s, Action[Status](lambda s1: CurrentSession.ProcessTimelineStatus(s1, False, False)))
135
136        def onPostProcessTimelineStatuses(self, sender, e):
137                if e.IsFirstTime and self.requireDisableApi():
138                        CurrentSession.TwitterService.Interval = 360000
139                        CurrentSession.TwitterService.Stop()
140                        CurrentSession.TwitterService.Start()
141
142        def onBeforeUnload(self, sender, e):
143                CurrentSession.AddInManager.GetAddIn[ConsoleAddIn]().UnregisterContext(DLRContextHelper.Wrap(CurrentSession, "ScrapingContext", ScrapingContext))
144                CurrentSession.PostProcessTimelineStatuses -= self.onPostProcessTimelineStatuses
145                self.interval = 0
146                self.thread.Abort()
147                self.thread.Join(5000)
148               
149        def requireDisableApi(self):
150                return self.config.GetValue("DisableTimelineApi")
151
152scraping = Scraping.instance()
153scraping.start()
Note: See TracBrowser for help on using the browser.