0

このビデオから、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
        }; 
    }
}
4

2 に答える 2

1

問題の解決策を見つけました。Twitter クラスは静的であってはならず、twitter コンテキストは twitter クラスの作成時にのみ作成する必要があります。

私が投稿したコードでは、AllTweetsAbout メソッドは静的であり、そのメソッドが呼び出されるたびに Twitter コンテキストが作成されます。おそらく、特定の時間内に多くのサインイン操作が発生すると、Twitter Api によって何らかの形でブロックされるため、これは機能しません。

于 2015-01-21T20:46:20.870 に答える