エキサイトブログに接続するためのJavaコード
エキサイトブログに接続し、最新記事の取得と記事の投稿を行うためのJavaのソースコードです。
まずは、メモまで。
ソースコード
以下、ソースコードの全文です。
import java.net.*; import javax.net.ssl.*; import java.io.*; import java.util.*; import java.util.regex.*; import java.util.zip.*; import java.text.*; /** * エキサイトブログ接続 * @author nattou_curry */ public class ExciteBlogAccess { // エキサイトブログのエンコード private static final String ENCODING = "UTF-8"; /** * 動作確認用のmainメソッド。 */ public static void main( String[] args ) throws Exception { // ログインする(通常)。 //String cookie = login( "ユーザID", "パスワード" ); // ログインする(SSL)。 String cookie = loginWithSSL( "ユーザID", "パスワード" ); // ログイン情報を取得する。 Map<String, String> loginInfo = getLoginInfo( cookie ); // 最新の記事情報の一覧を取得する。 List< Map<String, String>> articleList = getArticleList( loginInfo ); // 取得した記事情報を表示する。 for ( int i = 0; i < articleList.size(); ++i ) { Map<String, String> articleInfo = articleList.get( i ); String title = articleInfo.get( "title" ); String link = articleInfo.get( "link" ); String pubDate = articleInfo.get( "pubDate" ); String content = articleInfo.get( "content" ); System.out.println( title + " " + link + " " + pubDate + " " + content ); } // 記事を投稿する。 Map<String, String> postInfo = new HashMap<String, String>(); postInfo.put( "eid", loginInfo.get( "eid" ) ); postInfo.put( "subject", "タイトル"+ new Date().toString() ); postInfo.put( "content", "本文" ); postInfo.put( "pubDate", "2009/10/24 14:40" ); postNewEntry( cookie, postInfo ); } /** * ログインする(通常)。 * @param mail メールアドレス * @param password パスワード * @return クッキー */ public static String login( String user, String password ) throws Exception { // クッキー String cookie = null; // クッキー編集用のマップ Map<String, String> cookiesMap = new HashMap<String, String>(); ////////////////////////////////////////////////////////////////// // ログイン情報を送信し、クッキーを取得する。 ////////////////////////////////////////////////////////////////// HttpURLConnection conn = null; try { // ログイン画面への接続を開く。 conn = openConnection( "http://regist.excite.co.jp/idcenter/login_req/?pname=blog&brand=xcit&targeturl=http%3A%2F%2Fwww%2Eexblog%2Ejp" ); conn.setRequestProperty( "Host", "regist.excite.co.jp" ); // ログイン情報を送信する。 String query = "acctname=" + user + "&passwd=" + password; conn.setDoOutput( true ); conn.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded" ); conn.setRequestProperty( "Content-Length", query.length() + "" ); OutputStreamWriter out = new OutputStreamWriter( conn.getOutputStream(), ENCODING ); out.write( query ); out.flush(); out.close(); // クッキーを取得し、編集用のマップに設定する。 putCookiesToMap( conn, cookiesMap ); // 編集用のマップからクッキー文字列を作成する。 cookie = cookiesMapToString( cookiesMap ); } finally { // 接続を閉じる。 closeConnection( conn ); } ////////////////////////////////////////////////////////////////// // リダイレクトURLを取得する。 ////////////////////////////////////////////////////////////////// String redirectURL = null; conn = null; try { conn = openConnection( "http://regist.excite.co.jp/idcenter/login_cookie_check/?pname=blog&brand=xcit&targeturl=http%3A%2F%2Fwww.exblog.jp", cookie ); conn.setRequestProperty( "Host", "regist.excite.co.jp" ); // リダイレクトURLを取得する。 redirectURL = conn.getHeaderField( "Location" ); } finally { // 接続を閉じる。 closeConnection( conn ); } ////////////////////////////////////////////////////////////////// // リダイレクトURLへ接続し、追加のクッキーを取得する。 ////////////////////////////////////////////////////////////////// try { conn = openConnection( redirectURL, cookie ); conn.setRequestProperty( "Host", "www.exblog.jp" ); // クッキーを取得し、編集用のマップに設定する。 putCookiesToMap( conn, cookiesMap ); // マップからクッキー文字列を作成する。 cookie = cookiesMapToString( cookiesMap ); } finally { // 接続を閉じる。 closeConnection( conn ); } return cookie; } /** * ログインする(SSL)。 * @param mail メールアドレス * @param password パスワード * @return クッキー */ public static String loginWithSSL( String user, String password ) throws Exception { // クッキー String cookie = null; // クッキー編集用のマップ Map<String, String> cookiesMap = new HashMap<String, String>(); ////////////////////////////////////////////////////////////////// // ログイン情報を送信し、クッキーを取得する。 ////////////////////////////////////////////////////////////////// HttpURLConnection conn = null; try { // ログイン画面への接続を開く。 conn = openConnection( "https://sec.excite.co.jp/idcenter/login_req/?pname=blog&brand=xcit&targeturl=http%3A%2F%2Fwww%2Eexblog%2Ejp" ); conn.setRequestProperty( "Host", "sec.excite.co.jp" ); // ログイン情報を送信する。 String query = "acctname=" + user + "&passwd=" + password; conn.setDoOutput( true ); conn.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded" ); conn.setRequestProperty( "Content-Length", query.length() + "" ); OutputStreamWriter out = new OutputStreamWriter( conn.getOutputStream(), ENCODING ); out.write( query ); out.flush(); out.close(); // クッキーを取得し、編集用のマップに設定する。 putCookiesToMap( conn, cookiesMap ); // 編集用のマップからクッキー文字列を作成する。 cookie = cookiesMapToString( cookiesMap ); } finally { // 接続を閉じる。 closeConnection( conn ); } ////////////////////////////////////////////////////////////////// // リダイレクトURLを取得する。 ////////////////////////////////////////////////////////////////// String redirectURL = null; conn = null; try { conn = openConnection( "http://regist.excite.co.jp/idcenter/login_cookie_check/?pname=blog&brand=xcit&targeturl=http%3A%2F%2Fwww.exblog.jp", cookie ); conn.setRequestProperty( "Host", "regist.excite.co.jp" ); // リダイレクトURLを取得する。 redirectURL = conn.getHeaderField( "Location" ); } finally { // 接続を閉じる。 closeConnection( conn ); } ////////////////////////////////////////////////////////////////// // リダイレクトURLへ接続し、追加のクッキーを取得する。 ////////////////////////////////////////////////////////////////// conn = null; try { conn = openConnection( redirectURL, cookie ); conn.setRequestProperty( "Host", "www.exblog.jp" ); // クッキーを取得し、編集用のマップに設定する。 putCookiesToMap( conn, cookiesMap ); // 編集用のマップからクッキー文字列を作成する。 cookie = cookiesMapToString( cookiesMap ); } finally { // 接続を閉じる。 closeConnection( conn ); } return cookie; } /** * レスポンスヘッダよりクッキーを取得し、編集用のマップに設定する。 * @param conn HTTP接続 * @param cookieMap クッキー編集用のマップ */ private static void putCookiesToMap( HttpURLConnection conn, Map<String, String> cookiesMap ) { List<String> cookies = null; // レスポンスヘッダより、クッキーを取得する。 Map<String, List<String>> header = conn.getHeaderFields(); for ( String key : header.keySet() ) { if ( key != null && key.compareToIgnoreCase( "set-cookie" ) == 0 ) { cookies = header.get( key ); break; } } if ( cookies == null ) { // クッキーが取得できない場合: return; } // クッキーを分解し、編集用のマップに設定する。 for ( int i = 0; i < cookies.size(); ++i ) { String cookieLine = cookies.get( i ); String[] keyValuePairs = cookieLine.split( "; *" ); for ( int j = 0; j < keyValuePairs.length; ++j ) { String keyValuePair = keyValuePairs[j]; String[] keyValue = keyValuePair.split( "=" ); String key = keyValue[0]; String value = keyValue[1]; cookiesMap.put( key, value ); } } } /** * 編集用のマップからクッキー文字列を作成する。 * @param cookieMap クッキー編集用のマップ * @return クッキー文字列 */ private static String cookiesMapToString( Map<String, String> cookiesMap ) { StringBuffer cookie = new StringBuffer(); for ( String key: cookiesMap.keySet() ) { String value = cookiesMap.get( key ); cookie.append( key + "=" + value + "; " ); } return cookie.toString(); } /** * ログイン情報を取得する。 * @param cookie クッキー * @param ログイン情報のマップ。userid: ユーザID、url: URL、urlPart: URLのユーザ固有部分、eid: 投稿時に必要なID */ public static Map<String, String> getLoginInfo( String cookie ) throws Exception { String html; ////////////////////////////////////////////////////////////////// // トップ画面に接続する。 ////////////////////////////////////////////////////////////////// HttpURLConnection conn = null; try { conn = openConnection( "http://www.exblog.jp/", cookie ); conn.setRequestProperty( "Host", "www.exblog.jp" ); // トップ画面のHTMLを取得する。 html = getHTML( conn ); } finally { // 接続を閉じる。 closeConnection( conn ); } ////////////////////////////////////////////////////////////////// // トップ画面のHTMLより、ログイン情報を取得する。 ////////////////////////////////////////////////////////////////// // ユーザIDを取得する。 Pattern p = Pattern.compile( "<p class=\"f84 line130\"><b>(.*)</b>さん<br />エキサイトブログへようこそ!</p>" ); Matcher m = p.matcher( html ); if ( ! m.find() ) { // ユーザIDが見つからない: throw new Exception( "ログインしていません。" ); } String userid = m.group( 1 ); // ブログのURLを取得する。 p = Pattern.compile( "<input.*value=\"マイブログへ\".*onclick=\"self.location.href='(http://([^.]*).exblog.jp)';\">" ); m = p.matcher( html ); if ( ! m.find() ) { // URLが見つからない: throw new Exception( "URLが見つかりません。" ); } String url = m.group( 1 ); String urlPart = m.group( 2 ); // eidを取得する。 p = Pattern.compile( "<a href=\"http://www.exblog.jp/myblog/\\?eid=(.*)\">" ); m = p.matcher( html ); if ( ! m.find() ) { // eidが見つからない: throw new Exception( "eidが見つかりません。" ); } String eid = m.group( 1 ); Map<String, String> loginInfo = new HashMap<String, String>(); loginInfo.put( "userid", userid ); loginInfo.put( "url", url ); loginInfo.put( "urlPart", urlPart ); loginInfo.put( "eid", eid ); return loginInfo; } /** * 最新の記事情報の一覧を取得する。 * @param cookie クッキー * @param loginInfo ログイン情報。urlPart: URLのユーザ固有部分。 * @param 最新の記事情報の一覧。title: タイトル、link: 記事のURL、pubDate: 投稿日、content: 内容。 */ public static List<Map<String, String>> getArticleList( Map<String, String> loginInfo ) throws Exception { List<Map<String, String>> articleList = new ArrayList<Map<String, String>>(); ////////////////////////////////////////////////////////////////// // RSSに接続し、最新の記事一覧を取得する。 ////////////////////////////////////////////////////////////////// String urlPart = loginInfo.get( "urlPart" ); String rss; // RSSへの接続を開く。 HttpURLConnection conn = null; try { conn = openConnection( "http://rss.exblog.jp/rss/exblog/" + urlPart + "/index.xml" ); conn.setRequestProperty( "Host", "rss.exblog.jp" ); // RSSを取得する。 rss = getHTML( conn ); } finally { // 接続を閉じる。 closeConnection( conn ); } ////////////////////////////////////////////////////////////////// // RSSの各アイテムから記事情報を取得する。 ////////////////////////////////////////////////////////////////// Pattern p_item = Pattern.compile( "<item>(.*?)</item>", Pattern.DOTALL ); Pattern p_title = Pattern.compile( "<title>([^<]*)</title>" ); Pattern p_link = Pattern.compile( "<link>([^<]*)</link>" ); Pattern p_postContent = Pattern.compile( "<div class=\"(?:postContent|story)\">(.*?)</div>", Pattern.DOTALL ); Pattern p_pubDate = Pattern.compile( "<a href=\"?.*\"?>(....-..-.. ..:..)</a>", Pattern.CASE_INSENSITIVE ); Matcher m = p_item.matcher( rss ); while( m.find() ) { String item = m.group( 1 ); // タイトルを取得する。 String title = null; Matcher m2 = p_title.matcher( item ); if ( m2.find() ) { title = m2.group( 1 ); } // 記事のURLを取得する。 String link = null; m2 = p_link.matcher( item ); if ( m2.find() ) { link = m2.group( 1 ); } // URLにユーザ固有部分を含まない記事を除外する。 if ( link.indexOf( urlPart ) == -1 ) { continue; } String html = null; ////////////////////////////////////////////////////////////////// // 記事のURLに接続する。 ////////////////////////////////////////////////////////////////// conn = null; try { conn = openConnection( link ); conn.setRequestProperty( "Host", urlPart + ".exblog.jp" ); html = getHTML( conn ); } finally { // 接続を閉じる。 closeConnection( conn ); } ////////////////////////////////////////////////////////////////// // 記事の内容を取得する。 ////////////////////////////////////////////////////////////////// // 記事の内容を取得する。 m2 = p_postContent.matcher( html ); String content = ""; if ( m2.find() ) { content = m2.group( 1 ); // 内容の末尾のタグを取り除く。 int i = content.indexOf( "<DIV CLASS=TAGS>" ); if ( i >= 0 ) { content = content.substring( 0, i ); } // 内容の前後の空白を取り除く。 content = content.trim(); } // 投稿日を取得する。 m2 = p_pubDate.matcher( html ); String pubDate = null; if ( m2.find() ) { pubDate = m2.group( 1 ).replaceAll( "-", "/" ); } Map<String, String> articleInfo = new HashMap<String, String>(); articleInfo.put( "title", title ); articleInfo.put( "link", link ); articleInfo.put( "pubDate", pubDate ); articleInfo.put( "content", content ); articleList.add( articleInfo ); } return articleList; } /** * 記事を投稿する。 * @param cookie クッキー * @param postInfo 投稿情報。eid: 投稿時に必要なID、subject: タイトル、content: 内容、pubDate: 投稿日時 */ public static void postNewEntry( String cookie, Map<String, String> postInfo ) throws Exception { String eid = postInfo.get( "eid" ); String subject = postInfo.get( "subject" ); String content = postInfo.get( "content" ); String pubDate = postInfo.get( "pubDate" ); ////////////////////////////////////////////////////////////////// // 投稿日付を編集する。 ////////////////////////////////////////////////////////////////// SimpleDateFormat sdf_pubDate = new SimpleDateFormat( "yyyy/MM/dd HH:mm", Locale.US ); Date date = sdf_pubDate.parse( pubDate ); SimpleDateFormat sdf_year = new SimpleDateFormat( "yyyy" ); SimpleDateFormat sdf_month = new SimpleDateFormat( "MM" ); SimpleDateFormat sdf_day = new SimpleDateFormat( "dd" ); SimpleDateFormat sdf_hour = new SimpleDateFormat( "HH" ); SimpleDateFormat sdf_minute = new SimpleDateFormat( "mm" ); String pstyear = sdf_year.format( date ); String pstmonth = sdf_month.format( date ); String pstday = sdf_day.format( date ); String psthour = sdf_hour.format( date ); String pstminute = sdf_minute.format( date ); ////////////////////////////////////////////////////////////////// // 記事の投稿画面に接続する。 ////////////////////////////////////////////////////////////////// String html; HttpURLConnection conn = null; try { conn = openConnection( "http://www.exblog.jp/myblog/entry/new/?eid=" + eid, cookie ); conn.setRequestProperty( "Host", "www.exblog.jp" ); // 投稿画面のHTMLを取得する。 html = getHTML( conn ); } finally { // 接続を閉じる。 closeConnection( conn ); } ////////////////////////////////////////////////////////////////// // 投稿画面のHTMLより、投稿に必要な情報を取得する。 ////////////////////////////////////////////////////////////////// // 一時キーを取得する。 Pattern p = Pattern.compile( "<input type=\"hidden\" name=\"tempkey\" value=\"(.*)\">" ); Matcher m = p.matcher( html ); if ( ! m.find() ) { // 一時キーが見つからない: throw new Exception( "一時キーが見つかりません。" ); } String tempkey = m.group( 1 ); // 戻りURLを取得する。 p = Pattern.compile( "<input type=\"hidden\" name=\"rtnurl\" value=\"(.*)\">" ); m = p.matcher( html ); if ( ! m.find() ) { // 戻りURLが見つからない: throw new Exception( "戻りURLが見つかりません。" ); } String rtnurl = m.group( 1 ); ////////////////////////////////////////////////////////////////// // 記事を投稿する。 ////////////////////////////////////////////////////////////////// conn = null; try { conn = openConnection( "http://www.exblog.jp/myblog/entry/new/new.asp", cookie ); conn.setRequestProperty( "Host", "www.exblog.jp" ); String query = "eid=" + eid + "&tempkey=" + tempkey + "&rtnurl=" + URLEncoder.encode( rtnurl, "UTF-8" ) + "&cgiid=1" + "&cgname=" + URLEncoder.encode( "未分類", "UTF-8" ) + "&subject=" + URLEncoder.encode( subject, "UTF-8" ) + "&pstdate=1" + "&pstyear=" + pstyear + "&pstmonth=" + pstmonth + "&pstday=" + pstday + "&psthour=" + psthour + "&pstminute=" + pstminute + "&content=" + URLEncoder.encode( content, "UTF-8" ) + "&moresubject=" + "&morecontent=" + "&tag1=" + "&tag2=" + "&tag3=" + "&category_url=" + "&trackback_url=" + "&media_url_n=" + "&send_ping=1" + "&submit_button=" + URLEncoder.encode( "送信", "UTF-8" ); conn.setDoOutput( true ); conn.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded" ); conn.setRequestProperty( "Content-Length", query.length() + "" ); OutputStreamWriter out = new OutputStreamWriter( conn.getOutputStream(), ENCODING ); out.write( query ); out.flush(); out.close(); } finally { // 接続を閉じる。 closeConnection( conn ); } } /** * HTTP接続を開く。 * @param requestURL リクエストURL * @return HTTP接続 */ public static HttpURLConnection openConnection( String requestURL ) throws Exception { return openConnection( requestURL, null ); } /** * HTTP接続を開く。 * @param requestURL リクエストURL * @param cookie クッキー * @return HTTP接続 */ public static HttpURLConnection openConnection( String requestURL, String cookie ) throws Exception { URL url = new URL( requestURL ); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setInstanceFollowRedirects( false ); conn.setRequestProperty( "User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6" ); conn.setRequestProperty( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" ); conn.setRequestProperty( "Accept-Language", "ja,en-us;q=0.7,en;q=0.3" ); conn.setRequestProperty( "Accept-Encoding", "gzip,deflate" ); conn.setRequestProperty( "Accept-Charset", "Shift_JIS,utf-8;q=0.7,*;q=0.7" ); conn.setRequestProperty( "Keep-Alive", "300" ); conn.setRequestProperty( "Connection", "keep-alive" ); if ( cookie != null ) { conn.setRequestProperty( "Cookie", cookie ); } return conn; } /** * HTTP接続を閉じる。 * @param conn HTTP接続 */ public static void closeConnection( HttpURLConnection conn ) { try { OutputStream out = conn.getOutputStream(); out.close(); } catch ( Exception e ) {} try { InputStream in = conn.getInputStream(); in.close(); } catch ( Exception e ) {} } /** * 接続先のHTMLを取得する。 * @param conn 接続 * @return HTML */ public static String getHTML( HttpURLConnection conn ) throws Exception { ////////////////////////////////////////////////////////////////// // レスポンスヘッダより、GZIPを使用しているか判定する。 ////////////////////////////////////////////////////////////////// boolean usingGZIP = false; List<String> contentEncodings = conn.getHeaderFields().get( "Content-Encoding" ); if ( contentEncodings != null ) { for ( int i = 0; i < contentEncodings.size(); ++i ) { String contentEncoding = contentEncodings.get( i ); if ( contentEncoding.equals( "gzip" ) ) { usingGZIP = true; break; } } } ////////////////////////////////////////////////////////////////// // レスポンスデータを取得する。 ////////////////////////////////////////////////////////////////// StringBuffer buf = new StringBuffer(); BufferedReader in = null; try { // GZIPを使用しているかどうかにより、レスポンスの入力方法を変える。 if ( usingGZIP ) { // GZIPを使用している: in = new BufferedReader( new InputStreamReader( new GZIPInputStream( conn.getInputStream() ) , ENCODING ) ); } else { // GZIP を使用していない。 in = new BufferedReader( new InputStreamReader( conn.getInputStream(), ENCODING ) ); } int c; while ( ( c = in.read() ) != -1 ) { buf.append( (char) c ); } } finally { if ( in != null ) { in.close(); } } return buf.toString(); } /** * 【デバッグ用】レスポンスヘッダを表示する。 * @param conn HTTP接続 */ private static void printHeader( HttpURLConnection conn ) { Map<String, List<String>> header = conn.getHeaderFields(); for ( String key : header.keySet() ) { List<String> list = header.get( key ); System.out.println( "[" + key + "]" ); for ( int i = 0; i < list.size(); ++i ) { System.out.println( list.get( i ) ); } } } }