4 import java.io.UnsupportedEncodingException;
\r
5 import java.net.URLDecoder;
\r
6 import java.util.ArrayList;
\r
7 import java.util.Calendar;
\r
8 import java.util.Date;
\r
9 import java.util.GregorianCalendar;
\r
10 import java.util.HashMap;
\r
11 import java.util.regex.Matcher;
\r
12 import java.util.regex.Pattern;
\r
15 public class PlugIn_CSPSkyperfectTV2012 extends TVProgramUtils implements TVProgram,Cloneable {
\r
17 public PlugIn_CSPSkyperfectTV2012 clone() {
\r
18 return (PlugIn_CSPSkyperfectTV2012) super.clone();
\r
21 private static final String thisEncoding = "UTF-8";
\r
24 /*******************************************************************************
\r
26 ******************************************************************************/
\r
29 public String getTVProgramId() { return "スカパー!"; }
\r
32 public ProgType getType() { return ProgType.PROG; }
\r
34 public ProgSubtype getSubtype() { return ProgSubtype.CS; }
\r
38 public boolean isAreaSelectSupported() { return false; }
\r
40 /*******************************************************************************
\r
42 ******************************************************************************/
\r
45 public int getTimeBarStart() {return 5;}
\r
47 private int getDogDays() { return ((getExpandTo8())?(8):(7)); }
\r
50 /*******************************************************************************
\r
52 ******************************************************************************/
\r
54 private static final String XTYPE_BASIC = "e2";
\r
55 private static final String XTYPE_PREMIUM = "HD";
\r
57 private static final String CHNM_PREFIX_BS = "BS";
\r
58 private static final String CHNM_PREFIX_CS = "CS";
\r
59 private static final String CHNM_PREFIX_PR = "Ch.";
\r
61 private static final String CHID_PREFIX_BS = "BS";
\r
62 private static final String CHID_PREFIX_CS = "CS";
\r
63 private static final String CHID_PREFIX_PR = "HD";
\r
65 private final String MSGID = "["+getTVProgramId()+"] ";
\r
66 private final String ERRID = "[ERROR]"+MSGID;
\r
67 private final String DBGID = "[DEBUG]"+MSGID;
\r
70 /*******************************************************************************
\r
72 ******************************************************************************/
\r
74 protected ArrayList<ProgList> newplist;
\r
76 private HashMap<String,String> nf = null;
\r
77 private HashMap<String,String> gf = null;
\r
81 private static final HashMap<String,ProgGenre> genremap = new HashMap<String, TVProgram.ProgGenre>() {
\r
83 private static final long serialVersionUID = 1L;
\r
86 put("アニメ/特撮",ProgGenre.ANIME);
\r
87 put("こども向け/教育",ProgGenre.ANIME);
\r
89 put("映画",ProgGenre.MOVIE);
\r
90 put("洋画",ProgGenre.MOVIE);
\r
91 put("邦画",ProgGenre.MOVIE);
\r
93 put("ドラマ/演劇",ProgGenre.DORAMA);
\r
94 put("ドラマ",ProgGenre.DORAMA);
\r
96 put("劇場/公演",ProgGenre.THEATER);
\r
98 put("ドキュメンタリー/教養",ProgGenre.DOCUMENTARY);
\r
100 put("音楽",ProgGenre.MUSIC);
\r
102 put("バラエティー",ProgGenre.VARIETYSHOW);
\r
103 put("バラエティ",ProgGenre.VARIETYSHOW);
\r
105 put("スポーツ",ProgGenre.SPORTS);
\r
107 put("ニュース/報道",ProgGenre.NEWS);
\r
109 put("アダルト",ProgGenre.NOGENRE);
\r
115 public void loadProgram(String areaCode, boolean force) {
\r
116 // 新しい入れ物(トップ)を用意する
\r
117 newplist = new ArrayList<ProgList>();
\r
119 nf = new HashMap<String, String>();
\r
120 gf = new HashMap<String, String>();
\r
122 // 最終日の24時以降の情報は、+1したとこから取得する
\r
123 int counterMax = getSortedCRlist().size() * (getDogDays()+1);
\r
125 for ( Center c : getSortedCRlist() ) {
\r
126 if (getDebug()) System.err.println(DBGID+"load program: "+c.getCenter());
\r
127 _loadProgram(c, force, counter, counterMax);
\r
128 counter += getDogDays()+1;
\r
131 // 古いデータから補完できないかな?
\r
132 CompensatesPrograms(newplist);
\r
136 for ( String f : nf.keySet() ) {
\r
137 System.err.println(String.format("【デバッグ情報】未定義のフラグです: [%s]",f));
\r
139 for ( String g : gf.keySet() ) {
\r
140 System.err.println(String.format("【デバッグ情報】未定義のジャンルです: [%s]",g));
\r
145 pcenter = newplist;
\r
155 protected void _loadProgram(Center cr, boolean force, int counter, int counterMax) {
\r
161 ProgList pl = new ProgList();
\r
162 pl.Center = cr.getCenter();
\r
163 pl.CenterId = cr.getLink();
\r
167 if ( cr.getCenterOrig().startsWith(CHNM_PREFIX_BS) ) {
\r
170 else if ( cr.getCenterOrig().startsWith(CHNM_PREFIX_CS) ) {
\r
173 if ( onid != -1 ) {
\r
174 Matcher ma = Pattern.compile("(\\d+)").matcher(cr.getCenterOrig());
\r
176 ContentIdDIMORA.decodeChId(String.format("%04X%04X%04X", onid,0,Integer.valueOf(ma.group(1))));
\r
177 pl.ChId = ContentIdDIMORA.getContentId(0,"");
\r
181 pl.Area = cr.getAreaCode();
\r
182 pl.BgColor = cr.getBgColor();
\r
190 for ( int i=0; i<pl.pdate.size(); i++ ) {
\r
192 GregorianCalendar cal = CommonUtils.getCalendar(pl.pdate.get(i).Date);
\r
193 final String progCacheFile = String.format("%s%sSKP2012_%s_%d.txt", getProgDir(), File.separator, pl.CenterId, cal.get(Calendar.DAY_OF_MONTH));
\r
195 File f = new File(progCacheFile);
\r
196 if (force == true ||
\r
197 (f.exists() == true && isCacheOld(progCacheFile) == true) ||
\r
198 (f.exists() == false && isCacheOld(null) == true)) {
\r
200 String xtype = (pl.CenterId.startsWith(CHID_PREFIX_BS) || pl.CenterId.startsWith(CHID_PREFIX_CS)) ? XTYPE_BASIC : XTYPE_PREMIUM;
\r
201 String chid = xtype != XTYPE_PREMIUM ? pl.CenterId : pl.CenterId.replaceFirst("^"+CHID_PREFIX_PR, "");
\r
202 String dt = CommonUtils.getDateYMD(cal);
\r
203 String url = "http://bangumi.skyperfectv.co.jp/"+xtype+"/channel:"+chid+"/date:"+dt.substring(2)+"/";
\r
205 if ( pl.ChId.length() == 0 ) {
\r
206 url = "http://bangumi.skyperfectv.co.jp/api/version:3/search/date:"+dt.substring(2)+"/channel:"+pl.CenterId+"/?api_key=336eec3423";
\r
209 url = "http://www.skyperfectv.co.jp/xml/"+dt+"_"+pl.ChId.substring(2)+".xml";
\r
212 webToFile(url, progCacheFile, thisEncoding);
\r
214 reportProgress(getTVProgramId()+"(オンライン)を取得しました: ("+(counter+i)+"/"+counterMax+") "+pl.Center+"["+cal.get(Calendar.DAY_OF_MONTH)+"日] "+url);
\r
216 else if (CommonUtils.isFileAvailable(f,10)) {
\r
217 reportProgress(getTVProgramId()+"(キャッシュ)を取得しました: ("+(counter+i)+"/"+counterMax+") "+pl.Center+"["+cal.get(Calendar.DAY_OF_MONTH)+"日] "+progCacheFile);
\r
220 reportProgress(getTVProgramId()+"(キャッシュ)がみつかりません: ("+(counter+i)+"/"+counterMax+") "+pl.Center+"["+cal.get(Calendar.DAY_OF_MONTH)+"日] "+progCacheFile);
\r
224 String response = CommonUtils.read4file(progCacheFile, true);
\r
228 getPrograms(pl, i, response);
\r
230 if ( pl.ChId.length() == 0 ) {
\r
231 getPrograms(pl, i, response);
\r
234 getPrograms_basic(pl, i, response);
\r
238 catch ( Exception e ) {
\r
239 e.printStackTrace();
\r
244 refreshList(pl.pdate);
\r
246 catch (Exception e) {
\r
248 System.out.println("Exception: _loadProgram()");
\r
253 private void getDate(ProgList pl) {
\r
255 GregorianCalendar c = new GregorianCalendar();
\r
256 c.setTime(new Date());
\r
257 if ( CommonUtils.isLateNight(c) ) {
\r
259 c.add(Calendar.DATE, -1);
\r
261 // 最終日の24時以降の情報は、+1したとこから取得する
\r
262 for ( int i=0; i<getDogDays()+1; i++ ) {
\r
263 ProgDateList cl = new ProgDateList();
\r
264 cl.Date = CommonUtils.getDate(c);
\r
267 c.add(Calendar.DATE,1);
\r
272 private void refreshList(ArrayList<ProgDateList> pcenter) {
\r
273 // 前日分の情報は前日のリストに入れ替える
\r
274 for ( int i=0; i<pcenter.size(); i++ ) {
\r
275 ProgDateList pl = pcenter.get(i);
\r
276 ArrayList<ProgDetailList> pre = new ArrayList<ProgDetailList>();
\r
277 ArrayList<ProgDetailList> cur = new ArrayList<ProgDetailList>();
\r
278 for ( ProgDetailList pdl : pl.pdetail ) {
\r
279 if ( pl.Date.compareTo(pdl.accurateDate) >= 0 && CommonUtils.isLateNight(pdl.start.substring(0, 2)) ) {
\r
290 for ( ProgDetailList pdl : pre ) {
\r
291 pcenter.get(i-1).pdetail.add(pdl);
\r
294 String tbstart = CommonUtils.getTime(getTimeBarStart(),0);
\r
295 if ( pre.size() > 0 && pre.get(pre.size()-1).end.compareTo(tbstart) > 0 ) {
\r
296 if (getDebug()) System.err.println(DBGID+"overlap "+pre.get(pre.size()-1).end+" "+pre.get(pre.size()-1).title);
\r
297 // 日またがり(29時またがり)のものを当日のリストにもコピーする
\r
298 ProgDetailList pdl = pre.get(pre.size()-1).clone();
\r
299 pdl.length = (int)(CommonUtils.getDiffDateTime(pdl.accurateDate+" "+tbstart, pdl.accurateDate+" "+pdl.end)/60000L);
\r
305 for ( ProgDateList pl : pcenter ) {
\r
306 ArrayList<ProgDetailList> cur = new ArrayList<ProgDetailList>();
\r
307 String preend = pl.Date.substring(0,10)+" "+CommonUtils.getTime(getTimeBarStart(),0); // 最初の"前番組のおしり"は05:00
\r
308 for ( int i=0; i<pl.pdetail.size(); i++ ) {
\r
309 ProgDetailList pdl = pl.pdetail.get(i);
\r
310 if ( preend.compareTo(pdl.startDateTime) < 0 ) {
\r
311 // 前の番組との間に隙間があれば埋める
\r
312 ProgDetailList npdl = new ProgDetailList();
\r
313 npdl.title = npdl.splitted_title = "番組情報がありません";
\r
314 npdl.length = (int)(CommonUtils.getDiffDateTime(preend, pdl.startDateTime)/60000L);
\r
318 preend = pdl.endDateTime;
\r
323 // 24時以降の情報は日付+1したとこから取得しているので、最終日の次のリストは削除
\r
324 pcenter.remove(pcenter.size()-1);
\r
327 for ( ProgDateList pl : pcenter ) {
\r
330 for ( ProgDetailList pdl : pl.pdetail ) {
\r
331 pl.row += pdl.length;
\r
333 // おしりがとどかない場合(デメリット:これをやると、サイト側のエラーで欠けてるのか、そもそも休止なのかの区別がつかなくなる)
\r
334 if ( pl.row < 24*60 ) {
\r
335 ProgDetailList npdl = new ProgDetailList();
\r
336 npdl.title = npdl.splitted_title = "番組情報がありません";
\r
337 npdl.length = 24*60 - pl.row;
\r
338 pl.pdetail.add(npdl);
\r
339 pl.row += npdl.length;
\r
345 private void getPrograms(ProgList pl, int dtidx, String response) {
\r
347 ProgDateList pcl = pl.pdate.get(dtidx);
\r
349 String[][] keys = {
\r
350 { "class", "pg-title" },
\r
351 { "class", "start-time" },
\r
352 { "class", "end-time" },
\r
353 { "class", "pg-genre" },
\r
354 { "class", "pg-explanation" },
\r
355 { "id", "actor-name" },
\r
358 Matcher ma = Pattern.compile("<tbody\\s+id=\"event-\\d+\"[^>]*?>(.+?)</tbody>",Pattern.DOTALL).matcher(response);
\r
359 for ( int cnt = 0; ma.find(); cnt++ ) {
\r
360 ProgDetailList pdl = new ProgDetailList();
\r
361 String subtitle = "";
\r
362 String person = "";
\r
364 for ( String[] k : keys ) {
\r
365 Matcher mb = Pattern.compile("<span\\s+"+k[0]+"=\""+k[1]+"\"[^>]*?>\\s*(.+?)\\s*</span>",Pattern.DOTALL).matcher(ma.group(1));
\r
366 while ( mb.find() ) {
\r
367 if ( mb.group(1) == null ) {
\r
371 if ( k[1].equals("pg-title") ) {
\r
372 pdl.title = CommonUtils.unEscape(mb.group(1)).trim();
\r
374 else if ( k[1].equals("start-time") ) {
\r
375 pdl.start = mb.group(1);
\r
377 else if ( k[1].equals("end-time") ) {
\r
378 pdl.end = mb.group(1);
\r
380 GregorianCalendar c = CommonUtils.getCalendar(pcl.Date);
\r
382 if ( cnt == 0 && pdl.start.compareTo(pdl.end) > 0 ) {
\r
383 c.add(Calendar.DATE, -1);
\r
385 pdl.accurateDate = CommonUtils.getDate(c);
\r
386 pdl.startDateTime = CommonUtils.getDate(c,false)+" "+pdl.start;
\r
388 if ( pdl.start.compareTo(pdl.end) > 0 ) {
\r
389 c.add(Calendar.DATE, 1);
\r
391 pdl.endDateTime = CommonUtils.getDate(c,false)+" "+pdl.end;
\r
393 pdl.length = CommonUtils.getRecMinVal(pdl.start, pdl.end);
\r
395 else if ( k[1].equals("pg-genre") ) {
\r
396 Matcher mc = Pattern.compile("/large_genre:(.+?)/medium_genre:(.+?)/",Pattern.DOTALL).matcher(mb.group(1));
\r
399 String grstr = URLDecoder.decode(mc.group(1),"utf8").replaceAll("/", "/");
\r
400 ProgGenre gr = ProgGenre.get(grstr);
\r
401 if ( gr == null ) {
\r
402 gr = genremap.get(grstr);
\r
405 gr = ProgGenre.NOGENRE;
\r
406 gf.put(grstr,null);
\r
409 if ( pdl.genre == null || (pdl.genre == ProgGenre.NOGENRE && gr != ProgGenre.NOGENRE) ) {
\r
413 String sgstr = URLDecoder.decode(mc.group(2),"utf8").replaceAll("ィー", "ィ");
\r
414 ProgSubgenre sg = ProgSubgenre.get(gr, sgstr);
\r
415 if ( sg == null ) {
\r
417 ArrayList<ProgSubgenre> vals = ProgSubgenre.values(gr);
\r
418 sg = vals.get(vals.size()-1);
\r
421 } catch (UnsupportedEncodingException e) {
\r
422 e.printStackTrace();
\r
423 pdl.genre = ProgGenre.NOGENRE;
\r
424 pdl.subgenre = ProgSubgenre.NOGENRE_ETC;
\r
428 pdl.genre = ProgGenre.NOGENRE;
\r
429 pdl.subgenre = ProgSubgenre.NOGENRE_ETC;
\r
432 else if ( k[1].equals("pg-explanation") ) {
\r
433 pdl.detail += CommonUtils.decBr(CommonUtils.unEscape(mb.group(1))).trim()+"\n";
\r
435 else if ( k[1].equals("actor-name") ) {
\r
436 person += "、"+CommonUtils.unEscape(mb.group(1)).trim();
\r
442 if ( person.length() > 0 ) {
\r
443 person = person.substring(1);
\r
448 ((subtitle.length()>0)?(subtitle+DETAIL_SEP):(""))
\r
450 +((person.length()>0)?(DETAIL_SEP+person):(""));
\r
451 pdl.detail = pdl.detail.replaceFirst("[\r\n]+$", "");
\r
453 Matcher mb = Pattern.compile("<img\\s+src=\"/i/icon_(.+?)\\.gif",Pattern.DOTALL).matcher(ma.group(1));
\r
454 while ( mb.find() ) {
\r
455 if ( mb.group(1).equals("5.1") ) {
\r
456 pdl.addOption(ProgOption.SURROUND);
\r
458 else if ( mb.group(1).equals("jimaku") ) {
\r
459 pdl.addOption(ProgOption.SUBTITLE);
\r
461 else if ( mb.group(1).equals("2kakoku") ) {
\r
462 pdl.addOption(ProgOption.BILINGUAL);
\r
464 else if ( mb.group(1).equals("fukikae") ) {
\r
465 pdl.addOption(ProgOption.STANDIN);
\r
467 else if ( mb.group(1).equals("tajuu") ) {
\r
468 pdl.addOption(ProgOption.MULTIVOICE);
\r
470 else if ( mb.group(1).equals("r15") || mb.group(1).equals("r18") || mb.group(1).equals("adult") ) {
\r
471 pdl.addOption(ProgOption.RATING);
\r
473 else if ( mb.group(1).equals("ppv") ) {
\r
474 pdl.addOption(ProgOption.PV);
\r
476 else if ( mb.group(1).equals("nama") ) {
\r
477 pdl.addOption(ProgOption.LIVE);
\r
480 nf.put(mb.group(1), null);
\r
484 // タイトルから各種フラグを分離する
\r
485 doSplitFlags(pdl, nf);
\r
487 // サブタイトル分離(ポインタを活用してメモリを節約する)
\r
488 doSplitSubtitle(pdl);
\r
491 if ( ContentIdDIMORA.isValid(pl.ChId) ) {
\r
492 pdl.progid = pl.ChId;
\r
496 pdl.extension = false;
\r
497 pdl.nosyobo = false;
\r
499 pcl.pdetail.add(pdl);
\r
501 if (getDebug()) System.err.println(DBGID+"program: "+pdl.startDateTime+" - "+pdl.endDateTime+" "+pdl.length+"m "+pdl.noscrumble+" "+pdl.title);
\r
507 * こちらは番組IDがとれる代わりに出演者情報がとれなくなるので保留とする
\r
509 private void getPrograms_basic(ProgList pl, int dtidx, String response) {
\r
511 Matcher ma = Pattern.compile("<SIInformation(.+?)</SIInformation>",Pattern.DOTALL).matcher(response);
\r
512 while ( ma.find() ) {
\r
513 Matcher mb = Pattern.compile("eventId=\"(.+?)\".+?broadCastStartDate=\"(\\d{8})(\\d{4})",Pattern.DOTALL).matcher(ma.group(1));
\r
518 mb = Pattern.compile("<(.+?)>(.+?)</\\1>",Pattern.DOTALL).matcher(ma.group(1));
\r
519 while ( mb.find() ) {
\r
520 if ( mb.group(1).equals("ChannelName") ) {
\r
523 else if ( mb.group(1).equals("Title") ) {
\r
526 else if ( mb.group(1).equals("Synopsis") ) {
\r
529 else if ( mb.group(1).equals("Genres") ) {
\r
530 Matcher mc = Pattern.compile("<Genre majorGenreId=\".+?\" minorGenreId=\".+?\"",Pattern.DOTALL).matcher(mb.group(2));
\r
531 while ( mc.find() ) {
\r
542 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
543 * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここから ★★★★★
\r
544 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
552 public String getDefaultArea() {return "全国";}
\r
553 private String getDefaultCode() {return "SKP2012";}
\r
556 public void loadAreaCode() {
\r
557 aclist = new ArrayList<AreaCode>();
\r
558 AreaCode ac = new AreaCode();
\r
559 ac.setArea(getDefaultArea());
\r
560 ac.setCode(getDefaultCode());
\r
561 ac.setSelected(true);
\r
565 public void saveAreaCode() {}
\r
568 public String getArea(String code) { return(getDefaultArea()); }
\r
570 public String getCode(String area) { return(getDefaultCode()); }
\r
572 public String setSelectedAreaByName(String area) { return(getDefaultCode()); }
\r
574 public String getSelectedArea() { return(getDefaultArea()); }
\r
576 public String getSelectedCode() { return(getDefaultCode()); }
\r
579 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
580 * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここまで ★★★★★
\r
581 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
587 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
588 * ★★★★★ 放送局を選択する(TVCenterから降格)-ここから ★★★★★
\r
589 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
596 // 設定ファイルがなければWebから取得
\r
598 public void loadCenter(String code, boolean force) {
\r
600 if ( code == null ) {
\r
601 System.out.println(ERRID+"地域コードがnullです.");
\r
605 String centerListFile = getCenterListFile(getTVProgramId(), code);
\r
608 File f = new File(centerListFile);
\r
612 File f = new File(centerListFile);
\r
613 if (f.exists() == true) {
\r
614 @SuppressWarnings("unchecked")
\r
615 ArrayList<Center> tmp = (ArrayList<Center>)CommonUtils.readXML(centerListFile);
\r
616 if ( tmp != null ) {
\r
620 {CHNM_PREFIX_BS, CHID_PREFIX_BS},
\r
621 {CHNM_PREFIX_CS, CHID_PREFIX_CS},
\r
622 {CHNM_PREFIX_PR, CHID_PREFIX_PR},
\r
626 for ( Center cr : crlist ) {
\r
627 for ( String[] a : prs ) {
\r
628 if ( cr.getCenterOrig().startsWith(a[0]) ) {
\r
629 if ( ! cr.getLink().startsWith(a[1]) ) {
\r
630 Matcher ma = Pattern.compile("^.*?(\\d+)",Pattern.DOTALL).matcher(cr.getCenterOrig());
\r
632 String chid = a[1]+ma.group(1);
\r
633 System.err.println(DBGID+"converted: "+cr.getCenterOrig()+", "+cr.getLink()+" -> "+chid);
\r
645 System.out.println("放送局リストを読み込みました: "+centerListFile);
\r
649 System.out.println("放送局リストの読み込みに失敗しました: "+centerListFile);
\r
654 ArrayList<Center> newcrlist = new ArrayList<Center>();
\r
656 for ( String xtype : new String[] { XTYPE_BASIC,XTYPE_PREMIUM } ) {
\r
657 ArrayList<Center> crl = getCenters(xtype,code);
\r
658 if ( crl != null ) {
\r
659 reportProgress("放送局情報を取得しました: ("+xtype+") "+crl.size()+"ch");
\r
662 for ( Center cr : crl ) {
\r
667 if ( newcrlist.size() == 0 ) {
\r
668 System.err.println(ERRID+"放送局情報の取得結果が0件だったため情報を更新しません");
\r
672 crlist = newcrlist;
\r
673 attachChFilters(); // 放送局名にフィルタをかける
\r
677 private ArrayList<Center> getCenters(String xtype, String areacode) {
\r
679 ArrayList<Center> crl = new ArrayList<Center>();
\r
681 String url = String.format("http://bangumi.skyperfectv.co.jp/index/channel/%s/",xtype);
\r
682 if (getDebug()) System.err.println(DBGID+"get page: "+url);
\r
683 String response = webToBuffer(url,thisEncoding,true);
\r
684 if ( response == null ) {
\r
685 reportProgress("放送局情報の取得に失敗しました: "+xtype);
\r
689 Matcher ma = Pattern.compile("<td class=\"channel-icon\">\\s*<a href=\".*?/channel:(.+?)/\".*?>\\s*<img src=\".*?\" alt=\"(.+?)\"",Pattern.DOTALL).matcher(response);
\r
690 while ( ma.find() ) {
\r
691 String chid = (xtype.equals(XTYPE_PREMIUM) ? CHID_PREFIX_PR : "") + ma.group(1);
\r
692 String chnm = CommonUtils.toHANALNUM(CommonUtils.unEscape(ma.group(2))).replaceFirst("[ \\t]+▲$", "");
\r
695 if ( xtype.equals(XTYPE_PREMIUM) && ! chnm.startsWith(CHNM_PREFIX_PR) ) {
\r
696 chnm = CHNM_PREFIX_PR+chnm;
\r
699 Center cr = new Center();
\r
700 cr.setAreaCode(areacode);
\r
702 cr.setEnabled(true);
\r
703 cr.setCenterOrig(chnm);
\r
707 for ( Center ct : crl ) {
\r
708 if ( ct.getCenterOrig().compareTo(cr.getCenterOrig()) > 0 ) {
\r
715 if (getDebug()) System.err.println(DBGID+"center: "+cr.getCenterOrig()+", "+cr.getLink());
\r
722 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
723 * ★★★★★ 放送局を選択する(TVCenterから降格)-ここまで ★★★★★
\r
724 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r