スクリプトを作成する理由は、投稿を検索できるようにすることでした。これは、Facebookがサービスの一部としていかなる方法でも起動できず、LiveJournalを「活性化」するためです。 Facebookの投稿へのアクセスには必須の承認が必要なため、このサービスでは明らかに検索ロボットが許可されていません。 具体的には、私の場合、これは不便です。ソーシャルネットワークで公開するリンク、ビデオ、思考、「将来のために」公開することがよくあります。そして、この情報が必要になる瞬間がしばしばありますが、ほとんど見つかりません。
また、ここで公開されたスクリプトを使用して、既存のFacebookエントリのアーカイブを転送することができました。 私のFacebookの 2000を超えるアーカイブメッセージが、対応する日付でLiveJournalに送信されました。 つまり、LJがない場合は、すぐに情報をすぐに入力できます。
また、記事では、 既製のスクリプトをPerlに投稿します。これを使用して、LivejournalでFacebookステータスをブロードキャストできます。適切な設定がある場合は、そこからVkontakte、Twitter、RSSに送信し、ほぼすべてのブログエンジンに追加のWebサービスを使用します。
前文
2年前、私はFacebookで LJを辞めました 。 これは、LiveJournal自体の多くの問題、サービスの開発の阻害、そしてその結果、そこから私の友人が青と白のソーシャルネットワークに大量に離脱したことによるものでした。
同時に、LJは、投稿のサイズやデザインに大きな技術的制限を課さない柔軟な投稿形式を備えた唯一のオープンなブログサイトです。 LJにはまだ多くの興味深い性格があり、その多くは私の友人です。
LJの大きな利点は、検索エンジンに対するオープン性でした。 ブログに書いたものは、「検索エンジン」で見つけることができ、実際には、投稿の公開後数分でYandexまたはGoogleのインデックスが更新されます。 あなたの記事、メモ、または検索が友人だけでなく役に立つことを理解することで、この便利なものをどんどん書くようになります。 ただし、Habraに関しては同じロジックが機能します。
いくつかのソーシャルネットワークにメッセージを自動的に投稿するクロスシェアサービスを研究しました。 残念ながら、それらの賢明なものは見つかりませんでした。 ほぼすべての場所で、特別なインターフェースで記事を書くように強制されたり、LJが主要な場所として使用されたりしますが、個人的には不便です。 最も興味深いサービスはスタートアップIFTTT.comで 、「Twitterに表示-SMSで送信」、「Facebookに表示-Twitterで送信」、「雨が降る-SMSで警告 」などの形式の普遍的なルールを作成できます。 はい、一部のニーズに合わせて調整できますが、FacebookからLJに投稿することはできません。 すべてのクロスホスティングサービスには1つの大きな欠点があります-それらはあまりにも普遍的でカスタマイズが不十分であり、まれなものには人気のあるロシアのソーシャルネットワークが含まれます。 リストの同じLearnが非常にまれです。 また、RSSを介してLJで投稿を取得できる場合は、APIを介してのみそこに送信できます。
もう1つの理由があります。 コンテンツに応じて、投稿する場所を制御できるようにします。 たとえば、写真へのリンクではなく、LJで写真を自動的に公開する必要があると考えるかもしれません。 または、多くのサービスのように、投稿へのリンクではなく、投稿全体をTwitterに転送します。 これを行うには、自分のニーズに合わせてスクリプトを自分で修正できる必要があります。
その結果、目標はソーシャルネットワークTwitter、LiveJournal、Facebook、Vkontakteをカバーし、Facebookを投稿の「起動パッド」にすることでした。 LJ自身がVkontakteとTwitterに投稿できるほか、投稿をRSSにエクスポートしてDrupalと統合できるため、次のスキームが作成されました。





APIについて
私の意見では、Facebookは最もシックなAPIを持っています。 このインターフェイスを使用すると、ソーシャルネットワークに入力したデータに対して何でもできます。構造化された形式でデータを受信し、多くの便利なメカニズム、FQL、HTTPリクエストを通じて変更または削除します。 そして、この背景に対して、Facebookで動作する比較的少数のサードパーティアプリケーションが驚いた。
APIの使用に加えて、Facebookの簡易モバイルバージョンのページの解析も試みました。これにより、APIが提供するよりも多くの情報を引き出すことができました。 場合によっては、これは非常に便利なメカニズムです。 この場合、標準機能を完全に省くことができました。
Perlライブラリでは、すべてが正常であることが判明しました。Perlfor CPANでは、Facebookでの作業を実装するいくつかのモジュールが見つかりましたが、プロトコルが単純であるため、ほとんど必要ありません。 要求データはURLを介して送信され、結果はJSONで返されます。 LJに関しては、いくつかの異なるAPIがありますが、最も単純なのはLJ XML-RPCです。 LJ- LJ :: Simpleでかなり安定した作業を実装するPerl用の既製のモジュールを使用しました。
Facebookクロスホスティング機能
Facebookは、限られた権限で限られた期間、外部アプリケーションによって取得されたアクセストークンを介してアクセスされます。 セッションと受信したaccess_tokenの減衰時間は、2〜25時間で測定されます。 最長60日間の有効期間で長寿命トークンを取得することが可能です。 論理的には、減衰のたびにaccess_tokenを更新する必要があります。5日後または60日後です。上記のスクリプトでは、自動更新は提供されず、アクセストークンが腐敗しているという通知もありません。
2番目の機能は、あなたのメッセージが他のユーザーからのメッセージと一緒に壁に表示されることです。あなただけがクロスするべきだと思わない場合、他のユーザーがFacebookに間違ったことを投稿する可能性があります。 Facebookでは、デフォルトで、すべての友達が壁にあなたに何かを投稿する機会があります。特に、友達からあなたが「マーク」された他の誰かの写真にたくさんのコメントを得る機会は特に幸せです。 壁にいる他の人の投稿のモデレートをオンにしないと、クロスシェアの出現により、これらの写真もFacebookを超えてしまいます。
一部のFacebook投稿は、「情報に欠ける」ものです-アプリケーションから送信される一部のメッセージのように。 KrossposterはそれらをフィルタリングしてLivejournalに転送する方法を知っていますが、ここではもちろん誰もが自分で調整します。 一部の投稿は具体的には外観が異なります。たとえば、写真はFacebookリンクからLJ投稿に埋め込まれた大きな写真に変換されます。
また、LJに遡って投稿を投稿する際に「backdate」フラグを設定する必要性を考慮する必要があります。 これには、スクリプトの最初に特別な定数があります。 特徴は、2011年3月にLiveJournalで投稿を公開すると、(古い日付ではありますが)新鮮なものとしてフレンドストリームに配置され、twitterにリンクされると、新鮮なものとして公開されることです。 インターフェイスに特別なチェックを入れるか、APIを介してbackdateプロパティを設定すると、フレンドストリームから除外されます。 アーカイブを転送するには、backdateをインストールする必要がありますが、それを無効にすることができます。
そうですね、Facebookとの接続を削除する必要があります。そうしないと、閉じたループが発生します(スクリプト内で、保護がある場合に備えて)。
どうした
ここで、概念実証の一種である研究の過程で開発されたスクリプトを公開します。 また、記事の一部としての公開にも適合しています。たとえば、データベースに接続するための一般的なパラメータは個別のファイルに配置されず、コードは関数やファイルによって分解されず、重要でないものは削除されます。
クロスポスタアーキテクチャは、中間結果をデータベースに保存し、データベースからLJにレコードをエクスポートするという2段階の作業を意味します。 将来的には、このデータベースは独立したデータベースとして使用でき、ローカルデータを持ち、他のソーシャルネットワークRSSへのエクスポート用のスクリプトを簡単に追加できます。
facebook.plスクリプトは、データベースに保存するために使用されます。 その目的は、Facebookから壁からページを取得し、次のページがある場合はその識別子を提供し、そうでない場合は「すべて完了」を提供することです。 識別子はスクリプトパラメータなので、次のページを読み込むには、応答ですべて完了するまで、この識別子などを使用してスクリプトを呼び出す必要があります。
facebook.plを機能させるには、データベース接続パラメーター、LJのログの識別子を変更し、access_tokenを入力する必要があることに注意してください。 デバッグのために、 Facebook Graph API Explorerで短命のアクセストークンを作成できます。 60日間アクセスするには、アプリケーションを作成し、AppIdとSecretIdを取得してから、提供されたリンクを使用してアクセストークンを作成し、ドロップダウンリストからこのアプリケーションを選択する必要があります。 権利のリストに注意してください-チェックマークがいくつかないため、壁の投稿へのアクセスが制限される可能性があります。たとえば、他のユーザーや写真などからの再共有は、外部アプリケーションから見えなくなります。 スクリプトに不要なアクセスを残すことを恐れない場合は、一般にすべてのチェックボックスを配置することをお勧めします。
データベースからLiveJournalに投稿するには、update_lj.plスクリプトが使用されます。 この記事ではデバッグバージョンを使用します。facebook.plがデータベースから事前に準備した空の投稿を1つ取得し、LJに送信し、ページの識別子をLJに返し、投稿を送信済みとしてマークします。 これは中間バージョンです。スクリプトで作成された投稿をLiveJournalから削除するのは非常に不便なので、ここに残しておきます。
自動的に作成された誤った投稿がLJに補充される場合、投稿の最後にあるlj_change.plスクリプトを使用して、選択的な編集、削除、またはプロパティの変更を実行できます。
そのため、アーカイブを転送するには、必要な回数facebook.plを呼び出すbashスクリプトを使用してすべてのページを調べ、データベースに記録がある数だけupdatelj.plを実行する必要があります。 facebook.plを定期的に更新するには、1時間に1回または1日に1回クラウンを呼び出してから、同様のbashスクリプトの後にupdatelj.plを呼び出します。
私は、コメントや追加に加えて、これから外部の普遍的なサービスを望んでいるか、できるファンに喜んでいます。
CREATE TABLE `myposts` ( `id` int(11) NOT NULL AUTO_INCREMENT, `ctime` datetime DEFAULT NULL, // `message` text, // `link` text, // `picture_fb` text, // `posted_to_lj` int(11) DEFAULT NULL, // ? `lj_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, // `lj_item_id` int(11) DEFAULT NULL, // () `lj_anum` int(11) DEFAULT NULL, // , item_id html_id `lj_html_id` int(11) DEFAULT NULL, // (, , .html) `user` varchar(50) DEFAULT NULL, // ( ) PRIMARY KEY (`id`) )
#!/bin/bash # NEXT=`./facebook.pl`; echo $NEXT; while [ "$NEXT" != "all done" ] do NEXT=`$NEXT`; echo $NEXT; done
facebook.plソースコードを表示
#!/ usr / bin / perl
open qw ( : std : utf8 )を使用し ます。
LWPを使用する :: Simple ;
YAML :: Tinyを 使用し ます。
JSONを使用します。
URIを使用し ます。
DBIを使用し ます。
DBD :: MySQLを 使用し ます 。
$ DB_LOGIN = "======== DB-USER ========== ;;
$ DB_PASS = "======== DB-PASS ==========" ;
$ DATABASE = "======== DB-NAME ========== ;
$ USER = '======== YOUR-LJ-USER ===========' ;
私の $ access_token = '======== YOUR-ACCESS-TOKEN-SEE-GRAPH.FACEBOOK.COM-FOR-THE-DETAILS ==========' ;
#ARGV [0]は、facebookが次のページURLに「まで」CGIパラメーターの値として配置する値です。
$ until = $ ARGV [ 0 ] ;
my $ dbh = DBI- > connect ( "DBI:mysql:database = mysql; host = localhost" 、 $ DB_LOGIN 、 $ DB_PASS ) || die "データベースへの接続エラー:$!n" ;
$ dbh- > do ( "use $ DATABASE;" ) ;
#次の4行はFacebookグラフAPIリクエスト用
私の $ uri = 新しい URI ( 'https://graph.facebook.com/me/feed' ) ;
$ uri- > query_form ( { access_token => $ access_token 、 until => $ until 、 base_amount => 1 、 value => 1 } ) ;
私の $ resp = get ( "$ uri" ) ;
$ resp = defined $ resp ? decode_json ( $ resp ) : undef ;
$ next = $ resp- > {ページング} -> { next } ;
$ next =〜 /until =( . +) $ / ;
$ until = $ 1 ;
#スクリプトの結果、すべての完了メッセージまたは次の反復のbashコマンドを表示することにしました。 少し奇妙に見える...
if ( $ until != "" ) {
"./facebook.pl"を 印刷します 。 $まで 。 "n" ;
} その他
{
「すべて完了」を 印刷し ます。
}
#データベースの更新
私の $投稿 ( @ { $ resp- > { data } } ) {
$ ctime = $ post- > { created_time } ;
$ ctime =〜 /(dddd ) -( dd ) -( dd) .( dd):(dd):(dd) /;
( $ y 、 $ m 、 $ d 、 $ h 、 $ i 、 $ s ) = ( $ 1 、 $ 2 、 $ 3 、 $ 4 、 $ 5 、 $ 6 ) ;
$ time = "$ h:$ i:$ s" ;
$ sqltime = $ y 。 $ m 。 $ d 。 $ h 。 $ i 。 $ s
$ message = $ post- > {メッセージ} ;
$ link = $ post- > { link } ;
$ picture = $ post- > { picture } ;
$ sql = "select * from myposts where user = '$ USER' and ctime = '$ sqltime'" ;
$ sth = $ dbh- > prepare ( $ sql ) ;
$ sth- > 実行 ;
if ( $ sth- > rows == 0 ) {
$ sql = "myposts set user = '$ USER'に挿入、link =" $ dbh- > quote ( $ link ) 。 "、picture_fb =" 。 $ dbh- > quote ( $ picture ) 。 "、message =" 。 $ dbh- > quote ( $ message ) 。 "、ctime = '$ sqltime'" ;
#次の行は、twitterのような投稿をフィルタリングするためのものです。 それらの大半は、既存のFacebookやライブジャーナルへのリンクであるため、それらをスキップすることにしました。
if ( $ message !〜 / t .co // ) {
$ dbh- > do ( $ sql ) ;
}
}
}
update_ljソースコードを表示
#!/ usr / bin / perl
LJ :: シンプルを 使用し ます。
Date :: Manipを 使用し ます。
DBIを使用し ます。
DBD :: MySQLを 使用し ます 。
$ USER = '======== YOUR-LJ-USER ===========' ;
$ DB_LOGIN = "======== DB-USER ========== ;;
$ DB_PASS = "======== DB-PASS ==========" ;
$ LJ_NAME = "======== LJ-USER ===========" ;
$ LJ_PASS = "======== LJ-PASS ==========" ;
$ DATABASE = 'facebook' ;
$ DEBUG = 1 ;
#次の定数を「1」に設定することが非常に重要です
#このスクリプトを使用してすべての古いレコードを移行することにした場合。
$ HIDE_FROM_FRIENDS_WALLS = 0 ;
私の $ dbh = DBI- > connect (
「DBI:mysql:database = mysql; host = localhost」 、
$ DB_LOGIN 、
$ DB_PASS 、
) || die "データベースへの接続エラー:$!n" ;
my $ lj = new LJ :: シンプル ( {
ユーザー=> $ LJ_NAME 、
pass => $ LJ_PASS 、
サイト=> "livejournal.com:80" 、
} ) ;
( 定義済み $ lj )
|| die "$ 0:LiveJournalへのログインに失敗しました:$ LJ :: Simple :: errorn" ;
$ sql = "ctime、UNIX_TIMESTAMP(ctime)、リンク、メッセージ、picture_fb、mypostsからのid(user = '$ USER'およびlj_html_idはctime desc limit 0,1によるNULL順)を選択します。" ;
$ dbh- > do ( "use $ DATABASE;" ) ;
@row_ary = $ dbh- > selectrow_array ( $ sql ) ;
if ( $ row_ary [ 0 ] == "" ) { exit ; }
( $ ctime 、 $ ctime_ts 、 $ link 、 $ message 、 $ picture_fb 、 $ id ) = @row_ary ;
$ message =〜s / n / <br> <br> / g ; #HTML用のCRの準備
if ( $ DEBUG ) { print $ message 。 "n" ; }
#投稿のテキストから主題を構築
$ messagelength = length ( $ message ) ;
if ( $ messagelength > 50 ) {
$ i = index ( $ message 。 "" 、 "" ) ;
{
$ j = $ i ;
$ i = index ( $ message 。 "" 、 "" 、 $ i + 1 ) ;
} while ( $ i < 50 ) ;
$ subject = ( length ( $ message ) > 50 ) ? substr ( $ message 、 0 、 $ j ) 。 "..." : $メッセージ ;
if ( $ DEBUG ) { print "posting $ subject ... n" ; }
my %Entry = ( ) ; $ lj- > NewEntry ( %Entry ) || die "$ 0:新しいエントリの作成に失敗しました:$ LJ :: Simple :: errorn" ;
#croppedlink
$ croppedlink = ( length ( $ link ) > 50 ?
( substr ( $ link 、 0、50 ) 。 "..." )
:
$リンク ) ;
#小さな画像を大きな画像に置き換える
if ( $ picture_fb =〜 / https :// fbcdn / ) {
$ largepicture = $ picture_fb ;
$ largepicture = 〜s / _s / _n / g ;
$ entry = "<a href='$link'>" 。 $ croppedlink 。 "</a> <br>" 。
$メッセージ 。
"<br> <img src = '$ largepicture'>" ;
} else {
if ( $ link ne "" )
{
$ entry = "<table> <tr> <td> <img src =" "。$ picture_fb。" "align = left> </ td> <td> <a href = '" 。 $リンク 。 "'>" 。
$ croppedlink 。
"</a> <br> $ message <br clear=all> </ td> </ tr> </ table>" ;
} その他
{
$ entry = "$ messagenn <a href='$link'> $ link </a> <br> <img src =" $ picture_fb ">" ;
}
}
$ lj- > SetEntry ( %Entry 、 $ entry ) || die "$ 0:新しい投稿の準備に失敗しました-$ LJ :: Simple :: errorn" ;
$ lj- > SetSubject ( %Entry 、 $ subject ) ;
$ lj- > SetDate ( %Entry 、 $ ctime_ts ) ;
if ( $ HIDE_FROM_FRIENDS_WALLS ) { $ lj- > Setprop_backdate ( %Entry 、 1 ) ; }
my ( $ item_id 、 $ anum 、 $ html_id ) = $ lj- > PostEntry ( %Entry ) ;
( $ item_idを 定義 )
|| die "$ 0:仕訳入力の投稿に失敗しました:$ LJ :: Simple :: errorn" ;
if ( $ DEBUG ) { print "created item_id:" 。 $ item_id 。 "、anum:" 。 $ anum 。 "、html_id:" 。 $ html_id 。 "n" ; }
$ sql = "myposts set user = '$ USER'を更新、lj_ts = now()、lj_item_id = '$ item_id'、lj_anum = '$ anum'、lj_html_id = '" $ html_id 。 "'where id =" 。 $ id ;
$ dbh- > do ( $ sql ) ;
ソースコードを表示lj_change.pl
! / usr / bin / perl
Data :: Dumperを使用します。
POSIXを使用します。
LJ :: シンプルを使用します。
Time :: Localを使用します。
DBIを使用します。
DBD :: MySQLを使用します 。
$ LJ_LOGIN = "=========== LJ-LOGIN ============" ;
$ LJ_PASS = "=========== LJ-PASS ============" ;
$ DB_LOGIN = "=========== DB-LOGIN ============" ;
$ DB_PASS = "=========== DB-PASS =============" ;
$ DATABASE = "=========== DATABASE ============" ;
$ operation = "..." ; #setbackdate、purge ...
私の$ dbh = DBI- >接続(
「DBI:mysql:database = mysql; host = localhost」 、
$ DB_LOGIN、
$ DB_PASS、
) || die "データベースへの接続エラー:$!n" ;
$ dbh- > do ( "use $ DATABASE ;;" ) ;
$ sql = "mypostsからlj_item_idを選択します。ここで、lj_html_idはctime descのNULL順ではありません。" ;
$ results = $ dbh- > selectall_hashref ( $ sql、 'lj_item_id' ) ;
foreach my $ id ( keys % $ results ) {
#$ id2 = $ results-> {lj_item_id};
push @ids、$ id ;
}
my $ lj = new LJ :: シンプル ( {
ユーザー=> $ LJ_LOGIN、
pass => $ LJ_PASS、
サイト=> undef、
プロキシ=> undef、
} ) ;
(定義済み$ lj )
|| die "$ 0:LiveJournalへのログインに失敗しました:$ LJ :: Simple :: errorn" ;
print "logged on ... n" ;
私の%エントリ= ( ) ;
for ( @ids ) {
print "リクエストエントリ$ _... n" ;
( $ lj- > GetEntries ( % Entries、undef、 "one" 、$ _ )を定義)または"$ 0:エントリの取得に失敗しました-$ LJ :: Simple :: errorn" ;
私の$アイテム= $エントリ{ $ _ } ;
if ( $ operation == 'setbackdate' ) {
$ lj- > Setprop_backdate ( $ item、 1 )またはprint "$ 0:日付プロパティの設定に失敗しました-$ LJ :: Simple :: errorn" ;
$ lj- > EditEntry ( $ item )またはprint "$ 0:エントリの編集に失敗しました-$ LJ :: Simple :: errorn" ;
}
if ( $ operation == 'purge' ) {
$ lj- > EditEntry ( $ item、undef ) ;
}
$ sql = "mypostsセットを更新..." ;
$ dbh- > do ( $ sql ) ;
}
print "done.n" ;
exit ( 0 ) ;
PSところで、habra-editorによる構文の強調表示は非常にひどく機能します。 最初のスクリプトでは、ハイライトはデータベースに接続する行まで機能します(DBI-> connect):表示されるとすぐに、ソースタグはPerl構文のハイライトを停止します。 第二に、おそらくそれも失敗します。 フォントタグを使用して強調表示を行う必要がありました。