package tainavi;\r
\r
import java.io.File;\r
+import java.io.UnsupportedEncodingException;\r
+import java.net.URLDecoder;\r
import java.util.ArrayList;\r
-import java.util.Arrays;\r
import java.util.Calendar;\r
import java.util.Date;\r
import java.util.GregorianCalendar;\r
* 定数\r
******************************************************************************/\r
\r
- private static final String XTYPE_BASIC = "basic";\r
- private static final String XTYPE_PREMIUM = "premium";\r
+ private static final String XTYPE_BASIC = "e2";\r
+ private static final String XTYPE_PREMIUM = "HD";\r
\r
private static final String CHNM_PREFIX_BS = "BS";\r
private static final String CHNM_PREFIX_CS = "CS";\r
private static final String CHNM_PREFIX_PR = "Ch.";\r
\r
- private static final String CHID_PREFIX_CS = "e2";\r
- private static final String CHID_PREFIX_HD = "HD";\r
- private static final String CHID_PREFIX_SD = "SD";\r
-\r
- private static final String CHCD_PREFIX_BS = "bs";\r
- private static final String CHCD_PREFIX_CS = "cs";\r
-\r
+ private static final String CHID_PREFIX_BS = "BS";\r
+ private static final String CHID_PREFIX_CS = "CS";\r
+ private static final String CHID_PREFIX_PR = "HD";\r
+ \r
private final String MSGID = "["+getTVProgramId()+"] ";\r
private final String ERRID = "[ERROR]"+MSGID;\r
private final String DBGID = "[DEBUG]"+MSGID;\r
(f.exists() == true && isCacheOld(progCacheFile) == true) ||\r
(f.exists() == false && isCacheOld(null) == true)) {\r
//\r
- String url = null;\r
+ String xtype = (pl.CenterId.startsWith(CHID_PREFIX_BS) || pl.CenterId.startsWith(CHID_PREFIX_CS)) ? XTYPE_BASIC : XTYPE_PREMIUM;\r
+ String chid = xtype != XTYPE_PREMIUM ? pl.CenterId : pl.CenterId.replaceFirst("^"+CHID_PREFIX_PR, "");\r
String dt = CommonUtils.getDateYMD(cal);\r
- url = "http://bangumi.skyperfectv.co.jp/api/version:3/search/date:"+dt.substring(2)+"/channel:"+pl.CenterId+"/?api_key=336eec3423";\r
+ String url = "http://bangumi.skyperfectv.co.jp/"+xtype+"/channel:"+chid+"/date:"+dt.substring(2)+"/";\r
/*\r
if ( pl.ChId.length() == 0 ) {\r
url = "http://bangumi.skyperfectv.co.jp/api/version:3/search/date:"+dt.substring(2)+"/channel:"+pl.CenterId+"/?api_key=336eec3423";\r
\r
ProgDateList pcl = pl.pdate.get(dtidx);\r
\r
- Matcher ma = Pattern.compile("\\{(.+?)\\}[,\\]]",Pattern.DOTALL).matcher(response.replaceFirst("^.+?:\\[", ""));\r
- while ( ma.find() ) {\r
+ String[][] keys = {\r
+ { "class", "pg-title" },\r
+ { "class", "start-time" },\r
+ { "class", "end-time" },\r
+ { "class", "pg-genre" },\r
+ { "class", "pg-explanation" },\r
+ { "id", "actor-name" },\r
+ };\r
+ \r
+ Matcher ma = Pattern.compile("<tbody\\s+id=\"event-\\d+\"[^>]*?>(.+?)</tbody>",Pattern.DOTALL).matcher(response);\r
+ for ( int cnt = 0; ma.find(); cnt++ ) {\r
ProgDetailList pdl = new ProgDetailList();\r
String subtitle = "";\r
String person = "";\r
- Matcher mb = Pattern.compile("\"(.+?)\":(\\[(.*?)\\]|\"?(.*?)\"?)[,}]").matcher(ma.group(1));\r
- while ( mb.find() ) {\r
- if ( mb.group(1).equals("start") && mb.group(2) != null ) {\r
- GregorianCalendar c = new GregorianCalendar();\r
- c.setTimeInMillis(Long.valueOf(mb.group(2).replaceFirst("\\.\\d+$", ""))*1000L);\r
- pdl.accurateDate = CommonUtils.getDate(c);\r
- pdl.startDateTime = CommonUtils.getDateTime(c); \r
- pdl.start = CommonUtils.getTime(c).replaceFirst("^.+ ", "");\r
- }\r
- else if ( mb.group(1).equals("end") && mb.group(2) != null ) {\r
- GregorianCalendar c = new GregorianCalendar();\r
- c.setTimeInMillis(Long.valueOf(mb.group(2).replaceFirst("\\.\\d+$", ""))*1000L);\r
- pdl.endDateTime = CommonUtils.getDateTime(c); \r
- pdl.end = CommonUtils.getTime(c).replaceFirst("^.+ ", "");\r
- }\r
- else if ( mb.group(1).equals("title") && mb.group(4) != null ) {\r
- pdl.title = mb.group(4).replace("\\\"", "\"");\r
- }\r
- else if ( mb.group(1).equals("episode_title") && mb.group(4) != null ) {\r
- subtitle = mb.group(4);\r
- }\r
- else if ( mb.group(1).equals("explanation") && mb.group(4) != null ) {\r
- pdl.detail = mb.group(4).replace("\\\"", "\"").replace("\\n", "\n");\r
- }\r
- else if ( mb.group(1).equals("person") && mb.group(3) != null ) {\r
- String[] d = mb.group(3).split(",");\r
- for ( String s : d ) {\r
- Matcher mc = Pattern.compile("\"(.+?)\"").matcher(s);\r
- if ( mc.find() ) {\r
- person += "、"+mc.group(1);\r
- }\r
+ \r
+ for ( String[] k : keys ) {\r
+ Matcher mb = Pattern.compile("<span\\s+"+k[0]+"=\""+k[1]+"\"[^>]*?>\\s*(.+?)\\s*</span>",Pattern.DOTALL).matcher(ma.group(1));\r
+ while ( mb.find() ) {\r
+ if ( mb.group(1) == null ) {\r
+ continue;\r
}\r
- if ( person.length() > 0 ) {\r
- person = person.substring(1);\r
+ \r
+ if ( k[1].equals("pg-title") ) {\r
+ pdl.title = CommonUtils.unEscape(mb.group(1)).trim();\r
}\r
- }\r
- else if ( mb.group(1).equals("duration") ) {\r
- //pdl.length = Integer.valueOf(mb.group(4))/60; // 使えないっぽい\r
- }\r
- else if ( mb.group(1).equals("genres") && mb.group(3) != null ) {\r
- Matcher mc = Pattern.compile("\\[\"(.*?)\",\"(.*?)\"[,\\]]", Pattern.DOTALL).matcher(mb.group(3));\r
- if ( mc.find() ) {\r
+ else if ( k[1].equals("start-time") ) {\r
+ pdl.start = mb.group(1);\r
+ }\r
+ else if ( k[1].equals("end-time") ) {\r
+ pdl.end = mb.group(1);\r
\r
- String grstr = mc.group(1).replaceAll("/", "/");\r
- ProgGenre gr = ProgGenre.get(grstr);\r
- if ( gr == null ) {\r
- // 未定義のジャンルです!\r
- gr = ProgGenre.NOGENRE;\r
- gf.put(mc.group(1),null);\r
- }\r
- if ( pdl.genre == null || (pdl.genre == ProgGenre.NOGENRE && gr != ProgGenre.NOGENRE) ) {\r
- pdl.genre = gr;\r
+ GregorianCalendar c = CommonUtils.getCalendar(pcl.Date);\r
+ \r
+ if ( cnt == 0 && pdl.start.compareTo(pdl.end) > 0 ) {\r
+ c.add(Calendar.DATE, -1);\r
}\r
+ pdl.accurateDate = CommonUtils.getDate(c);\r
+ pdl.startDateTime = CommonUtils.getDate(c,false)+" "+pdl.start;\r
\r
- String sgstr = mc.group(2).replaceAll("ィー", "ィ");\r
- ProgSubgenre sg = ProgSubgenre.get(gr, sgstr);\r
- if ( sg == null ) {\r
- // 未定義のサブジャンルです!\r
- ArrayList<ProgSubgenre> vals = ProgSubgenre.values(gr);\r
- sg = vals.get(vals.size()-1);\r
+ if ( pdl.start.compareTo(pdl.end) > 0 ) {\r
+ c.add(Calendar.DATE, 1);\r
}\r
- pdl.subgenre = sg;\r
+ pdl.endDateTime = CommonUtils.getDate(c,false)+" "+pdl.end;\r
+ \r
+ pdl.length = CommonUtils.getRecMinVal(pdl.start, pdl.end);\r
}\r
- else {\r
- pdl.genre = ProgGenre.NOGENRE;\r
- pdl.subgenre = ProgSubgenre.NOGENRE_ETC;\r
+ else if ( k[1].equals("pg-genre") ) {\r
+ Matcher mc = Pattern.compile("/large_genre:(.+?)/medium_genre:(.+?)/",Pattern.DOTALL).matcher(mb.group(1));\r
+ if ( mc.find() ) {\r
+ try {\r
+ String grstr = URLDecoder.decode(mc.group(1),"utf8").replaceAll("/", "/");\r
+ ProgGenre gr = ProgGenre.get(grstr);\r
+ if ( gr == null ) {\r
+ gr = genremap.get(grstr);\r
+ if (gr == null) {\r
+ // 未定義のジャンルです!\r
+ gr = ProgGenre.NOGENRE;\r
+ gf.put(grstr,null);\r
+ }\r
+ }\r
+ if ( pdl.genre == null || (pdl.genre == ProgGenre.NOGENRE && gr != ProgGenre.NOGENRE) ) {\r
+ pdl.genre = gr;\r
+ }\r
+ \r
+ String sgstr = URLDecoder.decode(mc.group(2),"utf8").replaceAll("ィー", "ィ");\r
+ ProgSubgenre sg = ProgSubgenre.get(gr, sgstr);\r
+ if ( sg == null ) {\r
+ // 未定義のサブジャンルです!\r
+ ArrayList<ProgSubgenre> vals = ProgSubgenre.values(gr);\r
+ sg = vals.get(vals.size()-1);\r
+ }\r
+ pdl.subgenre = sg;\r
+ } catch (UnsupportedEncodingException e) {\r
+ e.printStackTrace();\r
+ pdl.genre = ProgGenre.NOGENRE;\r
+ pdl.subgenre = ProgSubgenre.NOGENRE_ETC;\r
+ }\r
+ }\r
+ else {\r
+ pdl.genre = ProgGenre.NOGENRE;\r
+ pdl.subgenre = ProgSubgenre.NOGENRE_ETC;\r
+ }\r
}\r
- }\r
- else if ( mb.group(1).equals("no_scramble") && mb.group(4) != null ) {\r
- pdl.noscrumble = (mb.group(4).equals("ノンスクランブル"))?(ProgScrumble.NOSCRUMBLE):(ProgScrumble.SCRUMBLED);\r
- }\r
- else if ( mb.group(1).equals("caption_dubbing") && mb.group(4) != null ) {\r
- if ( mb.group(4).contains("字幕") ) {\r
- pdl.option.add(ProgOption.SUBTITLE);\r
+ else if ( k[1].equals("pg-explanation") ) {\r
+ pdl.detail += CommonUtils.decBr(CommonUtils.unEscape(mb.group(1))).trim()+"\n";\r
+ }\r
+ else if ( k[1].equals("actor-name") ) {\r
+ person += "、"+CommonUtils.unEscape(mb.group(1)).trim();\r
}\r
}\r
}\r
\r
- // 算出してみる\r
- pdl.length = CommonUtils.getRecMinVal(pdl.start, pdl.end);\r
- //(int)(CommonUtils.getDiffDateTime(pdl.startDateTime, pdl.endDateTime)/60000L);\r
+ // 出演者\r
+ if ( person.length() > 0 ) {\r
+ person = person.substring(1);\r
+ }\r
\r
// くっつけてみる\r
pdl.detail =\r
+((person.length()>0)?(DETAIL_SEP+person):(""));\r
pdl.detail = pdl.detail.replaceFirst("[\r\n]+$", "");\r
\r
+ Matcher mb = Pattern.compile("<img\\s+src=\"/i/icon_(.+?)\\.gif",Pattern.DOTALL).matcher(ma.group(1));\r
+ while ( mb.find() ) {\r
+ if ( mb.group(1).equals("5.1") ) {\r
+ pdl.addOption(ProgOption.SURROUND);\r
+ }\r
+ else if ( mb.group(1).equals("jimaku") ) {\r
+ pdl.addOption(ProgOption.SUBTITLE);\r
+ }\r
+ else if ( mb.group(1).equals("2kakoku") ) {\r
+ pdl.addOption(ProgOption.BILINGUAL);\r
+ }\r
+ else if ( mb.group(1).equals("fukikae") ) {\r
+ pdl.addOption(ProgOption.STANDIN);\r
+ }\r
+ else if ( mb.group(1).equals("tajuu") ) {\r
+ pdl.addOption(ProgOption.MULTIVOICE);\r
+ }\r
+ else if ( mb.group(1).equals("r15") || mb.group(1).equals("r18") || mb.group(1).equals("adult") ) {\r
+ pdl.addOption(ProgOption.RATING);\r
+ }\r
+ else if ( mb.group(1).equals("ppv") ) {\r
+ pdl.addOption(ProgOption.PV);\r
+ }\r
+ else if ( mb.group(1).equals("nama") ) {\r
+ pdl.addOption(ProgOption.LIVE);\r
+ }\r
+ else {\r
+ nf.put(mb.group(1), null);\r
+ }\r
+ }\r
+ \r
// タイトルから各種フラグを分離する\r
doSplitFlags(pdl, nf);\r
\r
ArrayList<Center> tmp = (ArrayList<Center>)CommonUtils.readXML(centerListFile);\r
if ( tmp != null ) {\r
crlist = tmp;\r
+\r
+ String[][] prs = {\r
+ {CHNM_PREFIX_BS, CHID_PREFIX_BS},\r
+ {CHNM_PREFIX_CS, CHID_PREFIX_CS},\r
+ {CHNM_PREFIX_PR, CHID_PREFIX_PR},\r
+ };\r
+ \r
+ // 2013.11 新旧変換\r
+ for ( Center cr : crlist ) {\r
+ for ( String[] a : prs ) {\r
+ if ( cr.getCenterOrig().startsWith(a[0]) ) {\r
+ if ( ! cr.getLink().startsWith(a[1]) ) {\r
+ Matcher ma = Pattern.compile("^.*?(\\d+)",Pattern.DOTALL).matcher(cr.getCenterOrig());\r
+ if ( ma.find() ) {\r
+ String chid = a[1]+ma.group(1);\r
+ System.err.println(DBGID+"converted: "+cr.getCenterOrig()+", "+cr.getLink()+" -> "+chid);\r
+ cr.setLink(chid);\r
+ }\r
+ }\r
+ \r
+ break;\r
+ }\r
+ }\r
+ }\r
+ \r
// 放送局名変換\r
attachChFilters();\r
System.out.println("放送局リストを読み込みました: "+centerListFile);\r
\r
ArrayList<Center> crl = new ArrayList<Center>();\r
\r
- String url = String.format("http://www.skyperfectv.co.jp/channel/%s/list.html",xtype);\r
+ String url = String.format("http://bangumi.skyperfectv.co.jp/index/channel/%s/",xtype);\r
if (getDebug()) System.err.println(DBGID+"get page: "+url);\r
String response = webToBuffer(url,thisEncoding,true);\r
if ( response == null ) {\r
return null;\r
}\r
\r
- Matcher ma = Pattern.compile("<tr class=\"[^\"]*?ch-(.)d\">(.+?)</tr>",Pattern.DOTALL).matcher(response);\r
+ Matcher ma = Pattern.compile("<td class=\"channel-icon\">\\s*<a href=\".*?/channel:(.+?)/\".*?>\\s*<img src=\".*?\" alt=\"(.+?)\"",Pattern.DOTALL).matcher(response);\r
while ( ma.find() ) {\r
- Matcher mb = Pattern.compile("<div class=\"channel ch-channel\">.+?<a href=\"/channel/"+xtype+"/(bs|cs)?(\\d+)\\.html\">[ \\t]*(.+?)[ \\t]*</a>",Pattern.DOTALL).matcher(ma.group(2));\r
- if ( mb.find() ) {\r
- String chid_prefix = null;\r
- String chnm_prefix = null;\r
- if ( xtype.equals(XTYPE_BASIC) && CHCD_PREFIX_CS.equals(mb.group(1)) ) {\r
- chid_prefix = CHID_PREFIX_CS;\r
- chnm_prefix = CHNM_PREFIX_CS;\r
- }\r
- else {\r
- if ( xtype.equals(XTYPE_BASIC) ) {\r
- chid_prefix = CHID_PREFIX_CS;\r
- }\r
- else {\r
- if ( ma.group(1).equals("h") ) {\r
- chid_prefix = CHID_PREFIX_HD;\r
- }\r
- else {\r
- chid_prefix = CHID_PREFIX_SD;\r
- }\r
- }\r
- if ( CHCD_PREFIX_BS.equals(mb.group(1)) ) {\r
- chnm_prefix = CHNM_PREFIX_BS;\r
- }\r
- else {\r
- chnm_prefix = CHNM_PREFIX_PR;\r
- }\r
- }\r
+ String chid = (xtype.equals(XTYPE_PREMIUM) ? CHID_PREFIX_PR : "") + ma.group(1);\r
+ String chnm = CommonUtils.toHANALNUM(CommonUtils.unEscape(ma.group(2))).replaceFirst("[ \\t]+▲$", "");\r
\r
- if ( chid_prefix != null ) {\r
- Center cr = new Center();\r
- cr.setAreaCode(areacode);\r
- cr.setType("");\r
- cr.setEnabled(true);\r
- String name = CommonUtils.toHANALNUM(CommonUtils.unEscape(chnm_prefix+mb.group(2)+" "+mb.group(3)));\r
- String chid = null;\r
- if ( xtype.equals(XTYPE_BASIC) && name.contains("スター・チャンネル") ) {\r
- // e2のスター・チャンネルは専用の番組表が用意されていないみたい\r
- chid = String.format("%s%03d",CHID_PREFIX_HD,Integer.valueOf(mb.group(2))+425);\r
- }\r
- else {\r
- chid = chid_prefix+mb.group(2);\r
- }\r
- if ( ! name.endsWith("▲") && chid.startsWith("SD") ) {\r
- // スカパーのサイトにバグがあった!\r
- chid = chid.replaceFirst("^SD", "HD");\r
- if (getDebug()) System.err.println("+コード修正: "+name+" (SD->"+chid+")");\r
- }\r
- cr.setCenterOrig(name.replaceFirst("[ \\t]+▲$", ""));\r
- cr.setLink(chid);\r
- \r
- int idx = 0;\r
- for ( Center ct : crl ) {\r
- if ( ct.getCenterOrig().compareTo(cr.getCenterOrig()) > 0 ) {\r
- break;\r
- }\r
- idx++;\r
- }\r
- crl.add(idx, cr);\r
- \r
- if (getDebug()) System.err.println(DBGID+"center: "+cr.getCenterOrig()+", "+cr.getLink());\r
+ // 統一性がない\r
+ if ( xtype.equals(XTYPE_PREMIUM) && ! chnm.startsWith(CHNM_PREFIX_PR) ) {\r
+ chnm = CHNM_PREFIX_PR+chnm;\r
+ }\r
+ \r
+ Center cr = new Center();\r
+ cr.setAreaCode(areacode);\r
+ cr.setType("");\r
+ cr.setEnabled(true);\r
+ cr.setCenterOrig(chnm);\r
+ cr.setLink(chid);\r
+ \r
+ int idx = 0;\r
+ for ( Center ct : crl ) {\r
+ if ( ct.getCenterOrig().compareTo(cr.getCenterOrig()) > 0 ) {\r
+ break;\r
}\r
+ idx++;\r
}\r
+ crl.add(idx, cr);\r
+ \r
+ if (getDebug()) System.err.println(DBGID+"center: "+cr.getCenterOrig()+", "+cr.getLink());\r
}\r
\r
return crl;\r