このビデオから、Jonathan Worthington による Twitter の例を再構築しようとしました: https://www.youtube.com/watch?v=_VdIQTtRkb8
それはうまくいき始めます。しかし、しばらくするとストリームが停止します。入力された 3 番目の検索トピックで、アプリはツイートを受信しなくなりました。そして、私には理由がわかりません。時間に依存しないようです。検索トピックを変更せずに実行すると、続行されるためです。誰でも助けることができますか?
メインウィンドウのコードは次のとおりです。
public ObservableCollection<string> PositiveTweets = new ObservableCollection<string>();
public ObservableCollection<string> NegativeTweets = new ObservableCollection<string>();
public MainWindow()
{
InitializeComponent();
FocusManager.SetFocusedElement(this, SearchTextBox);
PositiveListBox.ItemsSource = PositiveTweets;
NegativeListBox.ItemsSource = NegativeTweets;
var keywords = Keywords.Create(new List<string> {"cool"}, new List<string> {"sucks"});
var sa = new SentimentAnalysis(keywords);
var topics = Observable
.FromEventPattern<TextChangedEventArgs>(SearchTextBox, "TextChanged")
.Select(e => ((TextBox) e.Sender).Text)
.Throttle(TimeSpan.FromSeconds(1));
var tweets = topics
.Select(Twitter.AllTweetsAbout)
.Switch()
.Select(sa.Score)
.Publish();
tweets.Connect();
var format = new Func<string, ScoredTweet, string>((topic, st) => String.Format("[user: @{0} | topic: {1} | score: {3}]\r\n{2}\r\n", st.Tweet.User, topic, st.Tweet.Text, st.Score));
var addToList = new Action<string, ObservableCollection<string>>((item, list) =>
{
if (list.Count == 4)
list.RemoveAt(3);
list.Insert(0, item);
});
tweets
.Where(x => x.Score >= 0)
.Sample(TimeSpan.FromSeconds(1))
.ObserveOnDispatcher()
.Subscribe(x => addToList(format(x.Tweet.Topic, x), PositiveTweets));
tweets
.Where(x => x.Score < 0)
.Sample(TimeSpan.FromSeconds(1))
.ObserveOnDispatcher()
.Subscribe(x => addToList(format(x.Tweet.Topic, x), NegativeTweets));
}
これは XAML コードです。
<StackPanel Margin="10">
<DockPanel>
<Label DockPanel.Dock="Left" Content="Search:" Margin="0,0,10,0" FontSize="20"/>
<TextBox Name="SearchTextBox" FontSize="20" Focusable="True"/>
</DockPanel>
<Label Content="positive" FontSize="20"/>
<ListBox Name="PositiveListBox" Height="250" FontSize="16"/>
<Label Content="negative" FontSize="20"/>
<ListBox Name="NegativeListBox" Height="250" FontSize="16"/>
</StackPanel>
IObservable の作成方法は次のとおりです。
readonly static SingleUserAuthorizer Auth = new SingleUserAuthorizer
{
CredentialStore = new InMemoryCredentialStore
{
ConsumerKey = ConfigurationManager.AppSettings["consumerKey"],
ConsumerSecret = ConfigurationManager.AppSettings["consumerSecret"],
OAuthToken = ConfigurationManager.AppSettings["authtoken"],
OAuthTokenSecret = ConfigurationManager.AppSettings["authtokensecret"],
}
};
public static IObservable<Tweet> AllTweetsAbout(string topic)
{
return Observable.Create<Tweet>(o =>
{
var twitterCtx = new TwitterContext(Auth);
var query = from s in twitterCtx.Streaming
where s.Type == StreamingType.Filter &&
s.Track == topic
select s;
var disposed = false;
query.StartAsync(s =>
{
if(disposed)
s.CloseStream();
else
o.OnNext(Tweet.Parse(s.Content, topic));
return Task.FromResult(true);
});
return Disposable.Create(() => disposed = true);
});
}
最後に、感情分析:
public class ScoredTweet
{
public Tweet Tweet { get; set; }
public int Score { get; set; }
}
public class SentimentAnalysis
{
private readonly Keywords _keywords;
public SentimentAnalysis(Keywords keywords)
{
_keywords = keywords;
}
public ScoredTweet Score(Tweet tweet)
{
return new ScoredTweet
{
Tweet = tweet,
Score = _keywords.Positive.Count(x => tweet.Text.Contains(x)) - _keywords.Negative.Count(x => tweet.Text.Contains(x))
};
}
}
public class Keywords
{
public List<string> Positive { get; private set; }
public List<string> Negative { get; private set; }
public static Keywords Create(List<string> positive, List<string> negative)
{
return new Keywords
{
Positive = positive,
Negative = negative
};
}
}