`
zhang_xzhi_xjtu
  • 浏览: 522111 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

使用豆瓣api查找本地电影评分来决定看什么电影

 
阅读更多
下载的电影过多,大把的时间花在到底要看什么电影上。
于是写了一个小程序,可以自动扫描电影在豆瓣的评分,并排序。

程序说明:
1 使用了反射和自定义classloader调用main方法,使得命令行不用指定jar包。
java  -cp .;allen_base-1.0.jar allen.program.Driver allen.douban.main.LocalFilmRating


        try {
            Class<?> type = myClassLoader.loadClass(mainClass);
            Method method = type.getMethod("main", String[].class);
            method.invoke(null, (Object) args0);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

2 使用了org.json包调用豆瓣API。
3 使用了多线程控制调用豆瓣API的频率。
    private static int           limitInMinutes = Config.LimitInMinutes;
    private static AtomicInteger invokeCounter  = new AtomicInteger(
                                                        limitInMinutes);
    private static Thread        monitorThread  = new Thread() {
                                                    @Override
                                                    public void run() {
                                                        while (true) {
                                                            try {
                                                                Thread.sleep(60000);
                                                            } catch (InterruptedException e) {
                                                                System.out
                                                                        .println(e);
                                                            }
                                                            invokeCounter
                                                                    .set(limitInMinutes);
                                                        }
                                                    }
                                                };

    private static void checkCounter() {
        int counter = invokeCounter.decrementAndGet();
        if (counter >= 0) {
            log.debug("pass counter = " + counter);
            return;
        } else {
            log.debug("deny counter = " + counter);
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            log.err(e);
        }

        checkCounter();
    }


4 使用了配置文件控制程序的运行。
#本地电影缓存目录。
MovieCacheDir=I:\douban_base\movie\

#本地个人缓存目录。
CelebrityCacheDir=I:\douban_base\celebrity\


#LocalFilmDirs=K:\todo,K:\allen_film
#本地电影目录。可以多个目录以逗号分隔。
LocalFilmDirs=K:\download


#豆瓣API的调用次数限制,每分钟。豆瓣API上面说不能超过40/min,实际上可以。
LimitInMinutes=40

#本地电影名称中需要过滤掉的字符串。
WordIgnoreInFilmTitle=BD,1280,高清,中字,CD,迅雷,下载,DVD,中英字幕,中英双字,720p

#可以处理的视频后缀名称。字母小写。
SuffixOfFiles=wmv,asf,asx,rm,rmvb,mpg,mpeg,mpe,dat,vob,dv,3gp,3g2,mov,avi,mkv,mp4,m4v,flv,xv

#不可以处理的文件后缀名称。字母小写。
IgnoreSuffixOfFiles=srt,torrent,idx,sub,rar,txt,jpg,zip,mp3


其中
WordIgnoreInFilmTitle配置了电影名称中被替换为空字符串的关键字。
SuffixOfFiles配置了可以处理的视频格式。
IgnoreSuffixOfFiles配置了不可以处理的文件格式。

5 为了减少对豆瓣API的调用次数,对于相似的电影名称进行了处理。
   /**
     * 处理相似的名字。2个名字有一个字符不同,其他相同,则认为2个名字相似。
     * */
    public static List<String> filterSimilarName(List<String> filmNames) {
        if (filmNames.size() <= 1) {
            return filmNames;
        }

        List<String> result = new ArrayList<String>();
        result.add(filmNames.get(0));

        //相同字符的index。
        int lastSimilarIndex = -1;

        for (int i = 1; i < filmNames.size(); i++) {
            String toHandleName = filmNames.get(i);
            String lastHandleName = result.get(result.size() - 1);
            int similarIndex = getSimilar(lastHandleName, toHandleName);

            if (similarIndex == -1) {
                if (lastSimilarIndex != -1) {
                    lastHandleName = lastHandleName.substring(0,
                            lastSimilarIndex)
                            + lastHandleName.substring(lastSimilarIndex + 1);
                    result.set(result.size() - 1, lastHandleName);
                }
                result.add(toHandleName);
                lastSimilarIndex = -1;
            } else {
                //不考虑连续相似的字符串,相似位置不同的情况。
                lastSimilarIndex = similarIndex;
            }
        }

        return result;
    }

    private static int getSimilar(String str1, String str2) {
        if (StringUtil.isEmptyString(str1) || StringUtil.isEmptyString(str2)) {
            return -1;
        }
        if (str1.length() != str2.length()) {
            return -1;
        }

        int similarIndex = -1;
        int differenceCount = 0;
        for (int i = 0; i < str1.length(); i++) {
            char c1 = str1.charAt(i);
            char c2 = str2.charAt(i);
            if (c1 != c2) {
                differenceCount++;
                similarIndex = i;
            }
        }
        if (differenceCount == 1) {
            return similarIndex;
        } else {
            return -1;
        }
    }


6 日志可以修改log4jconfig.xml控制。
7 结果可以在biz.log中查看。

本机跑结果如下:
INFO - 94    美丽人生
INFO - 93    阿甘正传
INFO - 91    天堂电影院
INFO - 91    鬼子来了
INFO - 91    搏击俱乐部
INFO - 91    海上钢琴师
INFO - 91    两杆大烟枪
INFO - 91    黄金三镖客
INFO - 91    三傻大闹宝莱坞
INFO - 90    指环王3:王者无敌
INFO - 90    美国往事
INFO - 90    教父2
INFO - 90    少年派的奇幻漂流
INFO - 89    楚门的世界
INFO - 89    上帝之城
INFO - 89    西游记大结局之仙履奇缘
INFO - 89    活着
INFO - 89    泰坦尼克号
INFO - 89    钢琴家
INFO - 88    指环王1:魔戒再现
INFO - 88    指环王2:双塔奇兵
INFO - 88    低俗小说
INFO - 88    天使爱美丽
INFO - 88    与狼共舞
INFO - 88    西游记第一百零一回之月光宝盒
INFO - 88    地球上的星星
INFO - 88    让子弹飞
INFO - 88    精英部队2:大敌当前
INFO - 87    大鱼
INFO - 87    黑客帝国
INFO - 87    剪刀手爱德华
INFO - 87    拯救大兵瑞恩
INFO - 87    芙蓉镇
INFO - 87    狮子王
INFO - 87    致命魔术
INFO - 86    猜火车
INFO - 86    纵横四海
INFO - 86    杀人回忆
INFO - 86    绿里奇迹
INFO - 86    西伯利亚的理发师
INFO - 86    喜宴
INFO - 86    V字仇杀队
INFO - 86    谍影重重3
INFO - 86    哈利·波特与死亡圣器(下)
INFO - 86    老爷车
INFO - 86    燃情岁月
INFO - 85    非常嫌疑犯
INFO - 85    洛城机密
INFO - 85    西西里的美丽传说
INFO - 85    费城故事
INFO - 85    末代皇帝
INFO - 85    美国X档案
INFO - 85    全金属外壳
INFO - 85    偷拐抢骗
INFO - 85    人工智能
INFO - 85    记忆碎片
INFO - 85    盲井
INFO - 85    赛德克·巴莱
INFO - 84    终结者2
INFO - 84    英国病人
INFO - 84    勇闯夺命岛
INFO - 84    加勒比海盗
INFO - 84    时时刻刻
INFO - 84    两小无猜
INFO - 84    黑天鹅
INFO - 84    朗读者
INFO - 84    这个男人来自地球
INFO - 84    蝙蝠侠:黑暗骑士崛起
INFO - 84    11度青春之《老男孩》
INFO - 83    歌剧魅影
INFO - 83    黑鹰坠落
INFO - 83    爱情是狗娘
INFO - 83    现代启示录
INFO - 83    不可饶恕
INFO - 83    荒岛余生
INFO - 83    谍影重重2
INFO - 83    了不起的狐狸爸爸
INFO - 83    凯尔经的秘密
INFO - 83    谜一样的双眼
INFO - 82    角斗士
INFO - 82    星球大战
INFO - 82    一级恐惧
INFO - 82    星球大战2:帝国反击战
INFO - 82    落水狗
INFO - 82    秋天的童话
INFO - 82    黑客帝国3:矩阵革命
INFO - 82    傲慢与偏见
INFO - 82    米尔克
INFO - 82    国王的演讲
INFO - 81    巴菲的奇妙命运
INFO - 81    夺宝奇兵3
INFO - 81    星球大战3:绝地归来
INFO - 81    罗塞塔
INFO - 81    喜剧之王
INFO - 81    黑客帝国2:重装上阵
INFO - 81    黑皮书
INFO - 81    霍比特人1:意外之旅
INFO - 81    碟中谍4
INFO - 81    社交网络
INFO - 81    黄海
INFO - 80    钢琴课
INFO - 80    英雄本色2
INFO - 80    小鬼当街
INFO - 80    卡特教练
INFO - 80    复仇者联盟
INFO - 80    葬礼上的死亡
INFO - 80    杀手没有假期
INFO - 80    X战警:第一战
INFO - 80    127小时
INFO - 79    苔丝
INFO - 79    大象
INFO - 79    精武英雄
INFO - 79    监狱风云
INFO - 79    星球大战前传1:幽灵的威胁
INFO - 79    九品芝麻官
INFO - 79    十二猴子
INFO - 79    鳗鱼
INFO - 79    你丫闭嘴!
INFO - 79    蝙蝠侠:侠影之谜
INFO - 79    星球大战前传3:西斯的复仇
INFO - 79    风吹麦浪
INFO - 79    四月三周两天
INFO - 79    白丝带
INFO - 79    猩球崛起
INFO - 79    大地惊雷
INFO - 79    单车少年
INFO - 78    迷失东京
INFO - 78    冰血暴
INFO - 78    樱桃的滋味
INFO - 78    夺宝奇兵
INFO - 78    国产凌凌漆
INFO - 78    华氏911
INFO - 78    加勒比海盗2:聚魂棺
INFO - 78    决战犹马镇
INFO - 78    老无所依
INFO - 78    立春
INFO - 78    人生不再重来
INFO - 77    云上的日子
INFO - 77    一条叫旺达的鱼
INFO - 77    碟中谍
INFO - 77    看得见风景的房间
INFO - 77    星球大战前传2:克隆人的进攻
INFO - 77    孔雀
INFO - 77    加勒比海盗3:世界的尽头
INFO - 77    卡波特
INFO - 77    美国黑帮
INFO - 77    潘神的迷宫
INFO - 77    孔雀王2 幻影城
INFO - 76    食神
INFO - 76    黄飞鸿之二:男儿当自强
INFO - 76    秋菊打官司
INFO - 76    毁灭之路
INFO - 76    黑社会
INFO - 76    功夫2
INFO - 76    理发师陶德
INFO - 76    看车人的七月
INFO - 76    预言者
INFO - 76    斗牛
INFO - 76    七个神经病
INFO - 75    性、谎言和录像带
INFO - 75    黄飞鸿之三:狮王争霸
INFO - 75    我的父亲母亲
INFO - 75    菊豆
INFO - 75    机械师
INFO - 75    虎胆龙威4
分享到:
评论
4 楼 a90120411 2014-01-28  
正在写一个Chrome的小插件。谢谢博主分享。
3 楼 zhang_xzhi_xjtu 2013-07-14  
我以前跑,也是经常被封ip的,你可以把每分钟抓取的次数限制调低一点。
JSONObject["subjects"]
这个是由于返回格式不符合导致的。
2 楼 mmxymm 2013-07-12  
另外一旦出现这个问题后,好像要过好久才能再次运行。我怀疑是豆瓣暂时屏蔽了IP访问吧。

能不能吧豆瓣的数据库抓下,然后在本地弄呢。。。瞎想中。
1 楼 mmxymm 2013-07-12  
你好,真的很好用哈。跟博主一样也是选电影花太久时间,真正看上的时候已经很晚了。

不过,我发现一旦目录里的文件过多(比如大于30个),我这里就会出现error,如下。不知博主有无时间能debug看看,呵呵。谢谢啦。


D:\pub_douban>java  -cp .;allen_base-1.0.jar allen.program.Driver allen.douban.m
ain.LocalFilmRating
Exception in thread "main" java.lang.RuntimeException: java.lang.reflect.Invocat
ionTargetException
        at allen.program.Driver.main(Driver.java:36)
Caused by: java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at allen.program.Driver.main(Driver.java:34)
Caused by: org.json.JSONException: JSONObject["subjects"] not found.
        at org.json.JSONObject.get(JSONObject.java:472)
        at org.json.JSONObject.getJSONArray(JSONObject.java:553)
        at allen.douban.handler.OnlineDataSearcher.searchMovieList(OnlineDataSea
rcher.java:123)
        at allen.douban.handler.OnlineDataSearcher.searchMovie(OnlineDataSearche
r.java:138)
        at allen.douban.handler.OnlineDataSearcher.searchMovieWithoutSave(Online
DataSearcher.java:75)
        at allen.douban.main.LocalFilmRating.main(LocalFilmRating.java:30)
        ... 5 more

D:\pub_douban>pause
Press any key to continue . . .

相关推荐

Global site tag (gtag.js) - Google Analytics