質問編集履歴

2 一応動作した版を追記

elpha

elpha score 12

2018/11/28 13:05  投稿

Node.jsでツイートをできるだけ(200件以上)検索するには
JavaScript、Node.jsともに初心者になります。
(Windows7のコマンドプロンプトから実行しています)
### やりたいこと
**「特定の30分間につぶやかれた、特定のハッシュタグを含んだツイート」をすべて一気に検索**
したいと思っています。
(手動で検索した限りではおよそ800~2000ツイートほどになるので、分割やスクロールなどの手間を省きたく…)
Stream APIは今年8月に廃止されたそうなので、REST APIを使うしかないようですが… こちらは一度に200件までしか検索できないようですね。
### 試したこと
> Node.jsでTwitter検索から100件を超えるツイートを取得したい
> https://qiita.com/ryo-a/items/53fe9eadcf719b817c9a
こちらを参考にしてしてみたところ、countの値をいくらにしても100件以内しか取得できませんでした。
> Twitter API Timeline解説
> http://nonbiri-tereka.hatenablog.com/entry/2014/03/06/220015
とりあえず**検索するたびに最後のツイートのIDを格納し、次はそのIDをmax_idにして検索**すればいいということはわかったのですが…
```Node.js
const Twit = require('twit');
const T = new Twit({
 各種キー
 app_only_auth: true
});
let lastId = '';
let params = {
   q: '#ハッシュタグ since:2018-11-28_00:00:00_JST until:2018-11-28_00:30:00_JST',
   count: 3,
   max_id: lastId,
   result_type: 'recent',
   include_entities: false
}
for(let i=0; i<3; i++){
   console.log('検索開始');
   params.max_id = lastId;
   T.get('search/tweets', params, (err, data, response) => {
       data.statuses.forEach(function(val, index, ar){
           console.log(index);
           console.log('@' + val.user.screen_name);
           console.log(val.text);
           lastId = val.id.str;
       });
   });
   console.log('最後のIDは' + lastId);
}
```
と3ツイート×3回の検索をしようとしてみると、コンソールはまず
```
検索開始
最後のIDは
検索開始
最後のIDは
検索開始
最後のIDは
```
と、まだ代入されていない状態のものが最初に3回ぶん表示されてしまい、そのあとで検索結果(3回とも同じ結果)が出てきます。
これはNode.jsゆえの、非同期だからこそ起こることでしょうか?
それともJavaScriptの何か初歩的な間違い(スコープなど)を犯しているのでしょうか?
ここさえ解決できれば、800ツイートでも2000ツイートでも(規制のかからないかぎり)検索できるとは思うのですが…
ご教授よろしくお願いいたします。
### 追記
やはり非同期通信が原因とのことでしたので、初めてながらasync/awaitというやつで書き換えてみましたが
何かが足りないのか、やはり検索結果は変わりません…
```Node.js
(略)  
async function main() {
   console.log('ループ開始');
   for(let i=0; i<3; i++){
       await search();
   }
}
function search() {
   return new Promise((resolve, reject) => {
       console.log('検索開始');
       params.max_id = lastId;
       T.get('search/tweets', params, (err, data, response) => {
           data.statuses.forEach(function(val, index, ar){
               console.log(index);
               console.log('@' + val.user.screen_name);
               console.log(val.text);
               lastId = val.id.str;
           });
       });
       console.log('最後のIDは' + lastId);
       resolve();
   });
}
main();
```
```
### 動作した版
いただいた回答を元にさらに修正したところ、無事動作しました
```Node.js
const Twit = require('twit');
const T = new Twit({
 consumer_key: "略",
 consumer_secret: "略",
 access_token_key: "略",
 access_token_secret: "略",
 app_only_auth: true
});
let num = 0;
let lastId = '';
let params = {
   q: '#ハッシュタグ since:2018-11-28_00:00:00_JST until:2018-11-28_00:30:00_JST',
   count: 3,
   max_id: lastId,
   result_type: 'recent',
   include_entities: false
}
!(async () => {
   for(let i=1; i<=3; i++){
       console.log('\n\n' + i + '回目の検索開始 ID' + lastId + '以前のツイートを検索');
       params.max_id = lastId;
       const result = await T.get('search/tweets', params);
       result.data.statuses.forEach(function(val, index, ar){
       num++;
           console.log(`\n${parseInt(index) + 1}個目のツイート (累計${num}個目)`);
           console.log('@' + val.user.screen_name);
           console.log(val.text.replace(/\r?\n/g, ''));
           lastId = val.id_str;
           console.log('ツイートのIDは' + lastId);
       })
       console.log('\n最後のツイートのIDは' + lastId);
   }
})();
```
このままだと再検索のたびに最初と最後のツイート内容が重複してしまうので、ほんとは再検索の際にIDを-1したいところですが
なまじIDの桁数が多いため計算に誤差が生じて面倒なので、ひとまず重複をよしとしています
> なぜJavaScriptで「76287755398823936」が正しく表示できないか、あるいはなぜRubyでも表せないか。
> https://7io.org/2011/07/02/21:11:55/
  • JavaScript

    22791 questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • Twitter

    870 questions

    Twitterは、140文字以内の「ツイート」と呼ばれる短文を投稿できるサービスです。Twitter上のほぼ全ての機能に対応するAPIが存在し、その関連サービスが多く公開されています。

  • Node.js

    2603 questions

    Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

1 async/awaitで書き換え

elpha

elpha score 12

2018/11/28 09:46  投稿

Node.jsでツイートをできるだけ(200件以上)検索するには
JavaScript、Node.jsともに初心者になります。
(Windows7のコマンドプロンプトから実行しています)
### やりたいこと
**「特定の30分間につぶやかれた、特定のハッシュタグを含んだツイート」をすべて一気に検索**
したいと思っています。
(手動で検索した限りではおよそ800~2000ツイートほどになるので、分割やスクロールなどの手間を省きたく…)
Stream APIは今年8月に廃止されたそうなので、REST APIを使うしかないようですが… こちらは一度に200件までしか検索できないようですね。
### 試したこと
> Node.jsでTwitter検索から100件を超えるツイートを取得したい
> https://qiita.com/ryo-a/items/53fe9eadcf719b817c9a
こちらを参考にしてしてみたところ、countの値をいくらにしても100件以内しか取得できませんでした。
> Twitter API Timeline解説
> http://nonbiri-tereka.hatenablog.com/entry/2014/03/06/220015
とりあえず**検索するたびに最後のツイートのIDを格納し、次はそのIDをmax_idにして検索**すればいいということはわかったのですが…
```Node.js
const Twit = require('twit');
const T = new Twit({
 各種キー
 app_only_auth: true
});
let lastId = '';
let params = {
   q: '#ハッシュタグ since:2018-11-28_00:00:00_JST until:2018-11-28_00:30:00_JST',
   count: 3,
   max_id: lastId,
   result_type: 'recent',
   include_entities: false
}
for(let i=0; i<3; i++){
   console.log('検索開始');
   params.max_id = lastId;
   T.get('search/tweets', params, (err, data, response) => {
       data.statuses.forEach(function(val, index, ar){
           console.log(index);
           console.log('@' + val.user.screen_name);
           console.log(val.text);
           lastId = val.id.str;
       });
   });
   console.log('最後のIDは' + lastId);
}
```
と3ツイート×3回の検索をしようとしてみると、コンソールはまず
```
検索開始
最後のIDは
検索開始
最後のIDは
検索開始
最後のIDは
```
と、まだ代入されていない状態のものが最初に3回ぶん表示されてしまい、そのあとで検索結果(3回とも同じ結果)が出てきます。
これはNode.jsゆえの、非同期だからこそ起こることでしょうか?
それともJavaScriptの何か初歩的な間違い(スコープなど)を犯しているのでしょうか?
ここさえ解決できれば、800ツイートでも2000ツイートでも(規制のかからないかぎり)検索できるとは思うのですが…
ご教授よろしくお願いいたします。
ご教授よろしくお願いいたします。
### 追記
やはり非同期通信が原因とのことでしたので、初めてながらasync/awaitというやつで書き換えてみましたが
何かが足りないのか、やはり検索結果は変わりません…
```Node.js
async function main() {
   console.log('ループ開始');
   for(let i=0; i<3; i++){
       await search();
   }
}
function search() {
   return new Promise((resolve, reject) => {
       console.log('検索開始');
       params.max_id = lastId;
       T.get('search/tweets', params, (err, data, response) => {
           data.statuses.forEach(function(val, index, ar){
               console.log(index);
               console.log('@' + val.user.screen_name);
               console.log(val.text);
               lastId = val.id.str;
           });
       });
       console.log('最後のIDは' + lastId);
       resolve();
   });
}
main();
```
  • JavaScript

    22791 questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • Twitter

    870 questions

    Twitterは、140文字以内の「ツイート」と呼ばれる短文を投稿できるサービスです。Twitter上のほぼ全ての機能に対応するAPIが存在し、その関連サービスが多く公開されています。

  • Node.js

    2603 questions

    Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る