4 import java.net.URISyntaxException;
6 import java.util.regex.Matcher;
7 import nicobrowser.entity.NicoContent;
8 import com.sun.syndication.feed.synd.SyndContentImpl;
9 import com.sun.syndication.feed.synd.SyndEntryImpl;
10 import com.sun.syndication.feed.synd.SyndFeed;
11 import com.sun.syndication.io.FeedException;
12 import com.sun.syndication.io.SyndFeedInput;
13 import java.io.BufferedInputStream;
14 import java.io.BufferedOutputStream;
15 import java.io.BufferedReader;
17 import java.io.FileOutputStream;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.InputStreamReader;
21 import java.io.Reader;
22 import java.io.StringReader;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Enumeration;
27 import java.util.LinkedHashMap;
28 import java.util.List;
30 import java.util.regex.Pattern;
31 import javax.swing.text.MutableAttributeSet;
32 import javax.swing.text.html.HTML;
33 import javax.swing.text.html.HTMLEditorKit;
34 import javax.swing.text.html.parser.ParserDelegator;
35 import javax.xml.parsers.DocumentBuilder;
36 import javax.xml.parsers.DocumentBuilderFactory;
37 import javax.xml.parsers.ParserConfigurationException;
38 import nicobrowser.entity.NicoContent.Status;
39 import nicobrowser.util.Result;
40 import nicobrowser.util.Util;
41 import org.apache.commons.io.FilenameUtils;
42 import org.apache.commons.logging.Log;
43 import org.apache.commons.logging.LogFactory;
44 import org.apache.http.HttpEntity;
45 import org.apache.http.HttpException;
46 import org.apache.http.HttpResponse;
47 import org.apache.http.HttpStatus;
48 import org.apache.http.NameValuePair;
49 import org.apache.http.client.entity.UrlEncodedFormEntity;
50 import org.apache.http.client.methods.HttpGet;
51 import org.apache.http.client.methods.HttpPost;
52 import org.apache.http.client.params.ClientPNames;
53 import org.apache.http.client.params.CookiePolicy;
54 import org.apache.http.cookie.Cookie;
55 import org.apache.http.entity.StringEntity;
56 import org.apache.http.impl.client.DefaultHttpClient;
57 import org.apache.http.message.BasicNameValuePair;
58 import org.w3c.dom.Document;
59 import org.w3c.dom.Element;
60 import org.w3c.dom.NodeList;
61 import org.xml.sax.SAXException;
67 public class NicoHttpClient {
69 private static Log log = LogFactory.getLog(NicoHttpClient.class);
70 private final DefaultHttpClient http;
71 private static final String LOGIN_PAGE =
72 "https://secure.nicovideo.jp/secure/login?site=niconico";
73 private static final String LOGOUT_PAGE =
74 "https://secure.nicovideo.jp/secure/logout";
75 private static final String WATCH_PAGE = "http://www.nicovideo.jp/watch/";
76 private static final String MY_LIST_PAGE_HEADER =
77 "http://www.nicovideo.jp/mylist/";
78 private static final String MOVIE_THUMBNAIL_PAGE_HEADER =
79 "http://www.nicovideo.jp/api/getthumbinfo/";
80 private static final String GET_FLV_INFO = "http://www.nicovideo.jp/api/getflv/";
81 private static final String SEARCH_HEAD = "http://www.nicovideo.jp/search/";
82 private static final String SEARCH_TAIL = "?sort=v";
83 private static final String ADD_MYLIST_PAGE = "http://www.nicovideo.jp/mylist_add/video/";
84 private static final String GET_THREAD_KEY_PAGE = "http://www.nicovideo.jp/api/getthreadkey?thread=";
86 public NicoHttpClient() {
87 http = new DefaultHttpClient();
88 http.getParams().setParameter(
89 ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);
94 * @param mail ログイン識別子(登録メールアドレス).
95 * @param password パスワード.
96 * @return 認証がOKであればtrue.
98 public boolean login(String mail, String password) throws URISyntaxException, HttpException, InterruptedException {
100 HttpPost post = new HttpPost(LOGIN_PAGE);
103 NameValuePair[] nvps = new NameValuePair[]{
104 new BasicNameValuePair("mail", mail),
105 new BasicNameValuePair("password", password),
106 new BasicNameValuePair("next_url", "")
108 post.setEntity(new UrlEncodedFormEntity(Arrays.asList(nvps), "UTF-8"));
110 //post.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
111 HttpResponse response = http.execute(post);
112 log.debug("ログインステータスコード: " + response.getStatusLine().getStatusCode());
115 HttpEntity entity = response.getEntity();
116 entity.consumeContent();
117 List<Cookie> cookies = http.getCookieStore().getCookies();
118 if (!cookies.isEmpty()) {
121 } catch (IOException ex) {
122 log.error("ログイン時に問題が発生", ex);
129 * @return ログアウトに成功すればtrue.
131 public boolean logout() throws URISyntaxException, HttpException, InterruptedException {
132 boolean result = false;
133 HttpGet method = new HttpGet(LOGOUT_PAGE);
135 HttpResponse response = http.execute(method);
136 log.debug("ログアウトステータスコード: " + response.getStatusLine().getStatusCode());
138 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
141 response.getEntity().consumeContent();
142 } catch (IOException ex) {
143 log.error("ログアウト時に問題が発生", ex);
150 * @param word 検索キーワード
153 public List<NicoContent> search(String word) {
154 log.debug("検索:" + word);
156 InputStream is = null;
157 List<NicoContent> conts = new ArrayList<NicoContent>();
158 String url = new String(SEARCH_HEAD + word + SEARCH_TAIL);
161 while (url != null) {
162 HttpGet get = new HttpGet(url);
163 HttpResponse response;
164 response = http.execute(get);
165 is = new BufferedInputStream(response.getEntity().getContent());
166 assert is.markSupported();
167 is.mark(1024 * 1024);
168 List<Result> results = Util.parseSerchResult(is);
169 for (Result r : results) {
170 NicoContent c = loadMyMovie(r.getId());
176 url = Util.getNextPage(is);
179 } catch (IOException ex) {
180 log.error("検索結果処理時に例外発生", ex);
186 * 「マイリスト登録数ランキング(本日)」の動画一覧を取得する。
189 public List<NicoContent> loadMyListDaily() throws URISyntaxException, HttpException, InterruptedException {
190 List<NicoContent> list = new ArrayList<NicoContent>();
191 String url = new String("http://www.nicovideo.jp/ranking/mylist/daily/all?rss=atom");
192 log.debug("全動画サイトのマイリスト登録数ランキング(本日)[全体] : " + url);
194 HttpGet get = new HttpGet(url);
196 BufferedReader reader = null;
198 HttpResponse response = http.execute(get);
199 reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
202 list = getNicoContents(reader);
203 deleteRankString(list);
204 response.getEntity().consumeContent();
205 } catch (FeedException ex) {
207 } catch (IOException ex) {
210 if (reader != null) {
213 } catch (IOException ex) {
222 * ニコニコ動画のRSSからコンテンツリストを取得する.
223 * @param url 取得するrssのurl.
226 public List<NicoContent> getContentsFromRss(String url) {
227 log.debug("アクセスURL: " + url);
228 List<NicoContent> list = accessRssUrl(url);
229 if (url.contains("ranking")) {
230 deleteRankString(list);
236 * rankingの場合、本当のタイトルの前に"第XX位:"の文字列が
238 * @param list 対象のリスト.
240 private void deleteRankString(List<NicoContent> list) {
241 for (NicoContent c : list) {
242 String title = c.getTitle();
243 int offset = title.indexOf(":") + 1;
244 c.setTitle(title.substring(offset));
250 * 「公開」設定にしていないリストからは取得できない.
252 * @param listNo マイリストNo.
255 public List<NicoContent> loadMyList(String listNo) {
256 String url = new String(MY_LIST_PAGE_HEADER + listNo + "?rss=atom");
257 log.debug("マイリストURL: " + url);
258 return accessRssUrl(url);
262 * 動画番号を指定したコンテンツ情報の取得.
263 * @param movieNo 動画番号.
266 public NicoContent loadMyMovie(String movieNo) {
267 NicoContent cont = null;
268 InputStream re = null;
269 List<SyndEntryImpl> list = null;
270 String url = new String(MOVIE_THUMBNAIL_PAGE_HEADER + movieNo);
271 log.debug("動画サムネイルURL: " + url);
276 get = new HttpGet(url);
277 HttpResponse response = http.execute(get);
278 re = response.getEntity().getContent();
279 // ドキュメントビルダーファクトリを生成
280 DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
282 DocumentBuilder builder = dbfactory.newDocumentBuilder();
283 // パースを実行してDocumentオブジェクトを取得
284 Document doc = builder.parse(re);
285 // ルート要素を取得(タグ名:site)
286 Element root = doc.getDocumentElement();
288 if ("fail".equals(root.getAttribute("status"))) {
289 log.warn("情報取得できません: " + movieNo);
293 NodeList list2 = root.getElementsByTagName("thumb");
294 cont = new NicoContent();
295 Element element = (Element) list2.item(0);
297 String watch_url = ((Element) element.getElementsByTagName("watch_url").item(0)).getFirstChild().
299 cont.setPageLink(watch_url);
301 String title = ((Element) element.getElementsByTagName("title").item(0)).getFirstChild().getNodeValue();
302 cont.setTitle(title);
305 // String first_retrieve = ((Element) element.getElementsByTagName("first_retrieve").item(0)).getFirstChild().getNodeValue();
306 // cont.setPublishedDate(DateFormat.getInstance().parse(first_retrieve));
308 // } catch (ParseException ex) {
309 // Logger.getLogger(NicoHttpClient.class.getName()).log(Level.SEVERE, null, ex);
310 } catch (SAXException ex) {
312 } catch (IOException ex) {
314 } catch (ParserConfigurationException ex) {
321 } catch (IOException ex) {
328 private List<NicoContent> accessRssUrl(String url) {
329 List<NicoContent> contList = new ArrayList<NicoContent>();
330 HttpGet get = new HttpGet(url);
331 BufferedReader reader = null;
333 HttpResponse response = http.execute(get);
334 reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
335 if (log.isTraceEnabled()) {
336 reader.mark(1024 * 1024);
338 String str = reader.readLine();
346 contList = getNicoContents(reader);
347 } catch (FeedException ex) {
348 log.warn("アクセスできません: " + url);
350 } catch (IOException ex) {
353 if (reader != null) {
356 } catch (IOException ex) {
364 private List<NicoContent> getNicoContents(Reader reader) throws FeedException {
365 List<SyndEntryImpl> list = null;
366 SyndFeedInput input = new SyndFeedInput();
367 SyndFeed feed = input.build(reader);
369 list = (List<SyndEntryImpl>) feed.getEntries();
371 List<NicoContent> contList;
373 contList = new ArrayList<NicoContent>();
375 contList = createContentsList(list);
380 private List<NicoContent> createContentsList(List<SyndEntryImpl> list) {
381 class CallBack extends HTMLEditorKit.ParserCallback {
383 private boolean descFlag;
384 private String imageLink = new String();
385 private StringBuilder description = new StringBuilder();
388 public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) {
389 log.debug("--------<" + t.toString() + ">--------");
391 if (HTML.Tag.IMG.equals(t)) {
392 imageLink = a.getAttribute(HTML.Attribute.SRC).toString();
397 public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
398 if (HTML.Tag.P.equals(t)) {
399 if ("nico-description".equals(
400 a.getAttribute(HTML.Attribute.CLASS).toString())) {
404 log.debug("--------<" + t.toString() + ">--------");
409 public void handleEndTag(HTML.Tag t, int pos) {
410 if (HTML.Tag.P.equals(t)) {
413 log.debug("--------</" + t.toString() + ">--------");
417 public void handleText(char[] data, int pos) {
419 description.append(data);
421 log.debug("--------TEXT--------");
425 private void printAttributes(MutableAttributeSet a) {
426 Enumeration e = a.getAttributeNames();
427 while (e.hasMoreElements()) {
428 Object key = e.nextElement();
429 log.debug("---- " + key.toString() + " : " + a.getAttribute(key));
433 public String getImageLink() {
437 public String getDescription() {
438 return description.toString();
442 List<NicoContent> contList = new ArrayList<NicoContent>();
444 for (SyndEntryImpl entry : list) {
445 NicoContent content = new NicoContent();
447 String title = entry.getTitle();
448 content.setTitle(title);
449 content.setPageLink(entry.getLink());
452 CallBack callBack = new CallBack();
453 for (SyndContentImpl sc : (List<SyndContentImpl>) entry.getContents()) {
455 Reader reader = new StringReader(sc.getValue());
456 new ParserDelegator().parse(reader, callBack, true);
457 } catch (IOException ex) {
458 log.error("RSSの読み込み失敗: " + content.getTitle());
463 contList.add(content);
469 * FLVファイルのURLを取得する. ログインが必要.
470 * また, 実際にFLVファイルの実態をダウンロードするには
471 * 一度http://www.nicovideo.jp/watch/ビデオIDに一度アクセスする必要があることに
473 * (参考: http://yusukebe.com/tech/archives/20070803/124356.html)
474 * @param videoId ニコニコ動画のビデオID.
475 * @return FLVファイル実体があるURL.
476 * @throws java.io.IOException ファイル取得失敗. 権限の無いファイルを取得しようとした場合も.
478 public VideoInfo getVideoInfo(String videoId) throws IOException {
479 final String realVideoId = getRealVideoId(videoId);
481 String accessUrl = GET_FLV_INFO + realVideoId;
482 if (realVideoId.startsWith("nm")) {
483 accessUrl += "?as3=1";
485 Map<String, String> map = getParameterMap(accessUrl);
487 LinkedHashMap<String, String> keyMap = new LinkedHashMap<String, String>();
488 if ("1".equals(map.get("needs_key"))) {
489 // 公式動画投稿者コメント取得用パラメータ.
490 keyMap = getParameterMap(GET_THREAD_KEY_PAGE + map.get(VideoInfo.KEY_THREAD_ID));
492 return new VideoInfo(realVideoId, map, keyMap);
495 private LinkedHashMap<String, String> getParameterMap(String accessUrl) throws IOException, IllegalStateException {
496 log.debug("アクセス: " + accessUrl);
497 HttpGet get = new HttpGet(accessUrl);
499 BufferedReader reader = null;
501 HttpResponse response = http.execute(get);
502 reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
504 StringBuilder strBuilder = new StringBuilder();
505 while ((str = reader.readLine()) != null) {
506 strBuilder.append(str);
508 resultString = strBuilder.toString();
509 response.getEntity().consumeContent();
510 log.debug(resultString);
512 if (reader != null) {
516 String[] params = resultString.split("&");
517 LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
518 for (String param : params) {
519 String[] elm = param.split("=");
520 map.put(elm[0], elm[1]);
526 * watchページへアクセスし, ビデオIDを取得する.
527 * soXXXXなど, 実際のビデオIDと異なる場合がある.
528 * @param videoId 取得したいビデオのビデオID.
530 * @throws IOException
532 private String getRealVideoId(String videoId) throws IOException {
533 String realId = accessWatchPage(videoId);
535 // ステータスコード302など、リダイレクトが必要な場合
536 if (!videoId.equals(realId)) {
537 realId = getRealVideoId(realId);
543 * WATCHページへアクセスする. getflvを行うためには, 必ず事前にWATCHページへアクセスしておく必要があるため.
544 * @param videoId ビデオID.
546 * @throws IOException
548 private String accessWatchPage(String videoId) throws IOException {
549 String realId = videoId;
550 String watchUrl = WATCH_PAGE + videoId;
551 log.debug("アクセス: " + watchUrl);
552 http.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false);
554 HttpGet get = new HttpGet(watchUrl);
555 HttpResponse response = http.execute(get);
556 if (response.containsHeader("Location")) {
557 realId = response.getFirstHeader("Location").getValue().replace("/watch/", "");
559 response.getEntity().consumeContent();
561 http.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, true);
567 * ニコニコ動画から動画ファイルをダウンロードする.
568 * @param vi getVideoInfoメソッドで取得したオブジェクト.
569 * @param saveDir ダウンロードしたファイルを保存するディレクトリ.
570 * @param np 保存するファイル名の命名規則. 拡張子は別途付与されるため不要.
571 * @param nowStatus ダウンロードしようとしている動画ファイルの, 現在のステータス.
572 * @param needLowFile エコノミー動画をダウンロードするのであればtrue.
573 * @return この処理を行った後の, 対象ファイルのステータス.
574 * @throws java.io.IOException ファイル取得失敗. 権限の無いファイルを取得しようとした場合も.
576 public GetFlvResult getFlvFile(VideoInfo vi, File saveDir, NamePattern np, Status nowStatus, boolean needLowFile,
577 ProgressListener listener) throws IOException, URISyntaxException, HttpException, InterruptedException {
579 final URL notifierUrl = vi.getSmileUrl();
581 String userName = null;
582 if (notifierUrl != null) {
583 HttpGet get = new HttpGet(notifierUrl.toString());
584 HttpResponse response = http.execute(get);
585 userName = Util.getUserName(response.getEntity().getContent());
586 response.getEntity().consumeContent();
589 final URL url = vi.getVideoUrl();
590 if (nowStatus == Status.GET_LOW || !needLowFile) {
591 if (url.toString().contains("low")) {
592 log.info("エコノミー動画のためスキップ: " + vi.getRealVideoId());
593 return new GetFlvResult(null, nowStatus, userName);
596 final boolean isNotLow = !url.toString().contains("low");
598 final File downloadFile = new File(saveDir, np.createFileName(vi.getRealVideoId(), isNotLow));
600 HttpGet get = new HttpGet(url.toURI());
601 HttpResponse response = http.execute(get);
602 String contentType = response.getEntity().getContentType().getValue();
603 log.debug(contentType);
604 log.debug(downloadFile.toString());
605 if ("text/plain".equals(contentType) || "text/html".equals(contentType)) {
606 log.error("取得できませんでした. サーバが混みあっている可能性があります: " + vi.getRealVideoId());
607 response.getEntity().consumeContent();
608 return new GetFlvResult(null, Status.GET_INFO, userName);
610 String ext = Util.getExtention(contentType);
611 final long fileSize = response.getEntity().getContentLength();
613 final int BUF_SIZE = 1024 * 32;
614 BufferedInputStream in = new BufferedInputStream(response.getEntity().getContent());
616 File file = new File(downloadFile.toString() + "." + ext);
617 log.info("保存します(" + fileSize / 1024 + "KB): " + file.getPath());
618 FileOutputStream fos = new FileOutputStream(file);
619 BufferedOutputStream out = new BufferedOutputStream(fos);
621 long downloadSize = 0;
623 byte[] buffer = new byte[BUF_SIZE];
624 while ((i = in.read(buffer)) != -1) {
625 out.write(buffer, 0, i);
627 listener.progress(fileSize, downloadSize);
630 response.getEntity().consumeContent();
633 if (url.toString().contains("low")) {
634 return new GetFlvResult(file, Status.GET_LOW, userName);
636 return new GetFlvResult(file, Status.GET_FILE, userName);
640 * ニコニコ動画から動画ファイルをダウンロードする.
641 * @param vi getVideoInfoメソッドで取得したオブジェクト.
642 * @param fileName ダウンロード後のファイル名. 拡張子は別途付与されるため不要.
643 * @param nowStatus ダウンロードしようとしている動画ファイルの, 現在のステータス.
644 * @param needLowFile エコノミー動画をダウンロードするのであればtrue.
645 * @return この処理を行った後の, 対象ファイルのステータス.
646 * @throws java.io.IOException ファイル取得失敗. 権限の無いファイルを取得しようとした場合も.
648 public GetFlvResult getFlvFile(VideoInfo vi, String fileName, Status nowStatus, boolean needLowFile,
649 ProgressListener listener) throws IOException, URISyntaxException, HttpException, InterruptedException {
650 String file = FilenameUtils.getName(fileName);
651 String dir = fileName.substring(0, fileName.length() - file.length());
652 NamePattern np = new NamePattern(file, "", "", "");
653 return getFlvFile(vi, new File(dir), np, nowStatus, needLowFile, listener);
657 * ニコニコ動画から動画ファイルをダウンロードする.
658 * @param vi getVideoInfoメソッドで取得したオブジェクト.
659 * @param fileName ダウンロード後のファイル名. 拡張子は別途付与されるため不要.
660 * @return この処理を行った後の, 対象ファイルのステータス.
661 * @throws java.io.IOException ファイル取得失敗. 権限の無いファイルを取得しようとした場合も.
663 public GetFlvResult getFlvFile(VideoInfo vi, String fileName, ProgressListener listener) throws IOException,
665 HttpException, InterruptedException {
666 return getFlvFile(vi, fileName, Status.GET_INFO, true, listener);
670 * ニコニコ動画から動画ファイルをダウンロードする.
672 * @param vi getVideoInfoメソッドで取得したオブジェクト.
673 * @return この処理を行った後の, 対象ファイルのステータス.
674 * @throws java.io.IOException ファイル取得失敗. 権限の無いファイルを取得しようとした場合も.
676 public GetFlvResult getFlvFile(VideoInfo vi) throws IOException, URISyntaxException, HttpException,
677 InterruptedException {
678 return getFlvFile(vi, vi.getRealVideoId(), Status.GET_INFO, true, ProgressListener.EMPTY_LISTENER);
681 public File getCommentFile(VideoInfo vi, String fileName) throws IOException {
682 return downloadComment(vi, fileName, false);
685 public File getTCommentFile(VideoInfo vi, String fileName) throws IOException {
686 return downloadComment(vi, fileName, true);
689 private File downloadComment(VideoInfo vi, String fileName, boolean isTcomm) throws IOException {
690 HttpResponse response = null;
691 BufferedOutputStream bos = null;
694 final HttpPost post = new HttpPost(vi.getMessageUrl().toString());
695 final String param = createCommendDownloadParameter(vi, isTcomm);
696 final StringEntity se = new StringEntity(param);
698 response = http.execute(post);
699 final InputStream is = response.getEntity().getContent();
700 final BufferedInputStream bis = new BufferedInputStream(is);
702 final String outputFileName = (fileName.endsWith(".xml")) ? fileName : fileName + ".xml";
703 bos = new BufferedOutputStream(new FileOutputStream(outputFileName));
705 final byte[] buf = new byte[1024 * 1024];
707 while ((read = bis.read(buf, 0, buf.length)) > 0) {
708 bos.write(buf, 0, read);
711 return new File(outputFileName);
712 } catch (Exception e) {
713 throw new IOException("コメントダウンロードに失敗しました。", e);
715 if (response != null) {
716 response.getEntity().consumeContent();
724 private String createCommendDownloadParameter(VideoInfo vi, boolean isTcomm) {
725 final String tcommStr = (isTcomm) ? "fork=\"1\" " : "";
726 StringBuilder builder = new StringBuilder();
727 Set<String> keySet = vi.getKeyMap().keySet();
728 for (String key : keySet) {
729 builder.append(key + "=\"" + vi.getKeyMap().get(key) + "\" ");
731 final String officialOption = builder.toString();
733 return "<thread " + VideoInfo.KEY_USER_ID + "=\"" + vi.getUserId() + "\" res_from=\"" + vi.getResFrom()
734 + "\" version=\"20061206\" thread=\"" + vi.getThreadId() + "\" " + tcommStr + officialOption + "/>";
738 * 動画をマイリストへ登録する. ログインが必要.
739 * @param myListId 登録するマイリストのID.
740 * @param videoId 登録する動画ID.
741 * @throws IOException 登録に失敗した.
743 public void addMyList(String myListId, String videoId) throws IOException {
744 String itemType = null;
745 String itemId = null;
747 HttpGet get = new HttpGet(ADD_MYLIST_PAGE + videoId);
748 HttpResponse response = http.execute(get);
749 HttpEntity entity = response.getEntity();
751 InputStream is = entity.getContent();
752 BufferedReader reader = new BufferedReader(new InputStreamReader(is));
755 Pattern pattern = Pattern.compile("input type=\"hidden\" name=\"item_type\" value=\"(.+)\"");
756 while ((line = reader.readLine()) != null) {
757 Matcher m = pattern.matcher(line);
759 itemType = m.group(1);
764 pattern = Pattern.compile("input type=\"hidden\" name=\"item_id\" value=\"(.+)\"");
765 while ((line = reader.readLine()) != null) {
766 Matcher m = pattern.matcher(line);
773 pattern = Pattern.compile("NicoAPI\\.token = \"(.*)\";");
774 while ((line = reader.readLine()) != null) {
775 Matcher m = pattern.matcher(line);
782 entity.consumeContent();
785 if (itemType == null || itemId == null || token == null) {
786 throw new IOException("マイリスト登録に必要な情報が取得できませんでした。 "
787 + "マイリスト:" + myListId + ", 動画ID:" + videoId + ", item_type:" + itemType + ", item_id:" + itemId
788 + ", token:" + token);
791 StringEntity se = new StringEntity(
792 "group_id=" + myListId
793 + "&item_type=" + itemType
794 + "&item_id=" + itemId
795 + "&description=" + ""
796 + "&token=" + token);
798 HttpPost post = new HttpPost("http://www.nicovideo.jp/api/mylist/add");
799 post.setHeader("Content-Type", "application/x-www-form-urlencoded");
801 response = http.execute(post);
802 int statusCode = response.getStatusLine().getStatusCode();
803 response.getEntity().consumeContent();
804 if (statusCode != 200) {
805 throw new IOException("マイリスト登録に失敗" + "マイリスト:" + myListId + ", 動画ID:" + videoId);