前言
趁着五一假期,自己也没出去玩,所以有大把的空闲时间,想到马上实习去了,可能项目要交接,于是自己决定重构一下代码… 因为我是在师兄的代码的基础上进行维护修改的,改到后面真的是越来越复杂,越来越麻烦,以至于现在我随便加点新功能,完全没有可扩展性,而且代码没有任何可读性…我都不知道我是怎么读下去这个代码并且修改的,简直就是在 ”shi上雕花“,想想还是不能坑别人,于是狠下心来,决定将原来用 node 写的改成 java,还好,一切都比较顺利,经过2天的重构 + 1天的测试,能够顺利跑通了,如果后期要交接的话,就将这份代码上线…
为了最大限度的减少修改和对前期代码的兼容,我只修改了 node 部分的代码,全部转成 java,这样同时也解决了 kafka 对 node 无法进行 kerberos 加密的缺点,终于不用裸奔了… 但是目前代码对谷歌验证的封堵能力还没有进行考验,所以不到万不得已这份代码还是不会上线的…除非真的要添加新功能或者要交接…
现在记录一下在重构中遇到的一些小问题。「代码直接在 leetcode 工程中写的,没有独立出来,文件夹名字为 ReWrite_xxx_List」
问题
Q1:Java版本的 Kafka 中的序列化和反序列化,不支持 JSON,而 Python 那个模块的代码要求用 json 传递消息
我发现 Java 这边的 String,要想正常的在 python 模块变为 json,就必须使得 String 中的单引号全部变为双引号,否则就无法转换「json.loads(str) 会报错」。
例如:
1
2 > String msg = "{\"params\": \"apple\", \"task_id\": \"W2155_1588604670842_0310\",\"is_cycle\": 0, \"task_type\": 9, \"cron_expression\": \"---\", \"priority \": 1, \"operation\": \"init\", \"quantity\": 100, \"comments\": 0, \"follower\": 0, \"followed\": 0, \"u_id\": \"0452mlppa555\", \"address\": \"0452_m\", \"remain_count\": 50}";
>
这样就没问题,同理,在我尝试抓取列表页的简历的 name 时,也同样发现了这个问题,但是当时没有注意到,在 selenium_test 文件夹下的 url_test 中,有
1
2 > JSONObject resultsJson = (JSONObject) JSONObject.parse(results);
>
要想尝试转换成功,就必须把 results 中的 单引号 全部替换成 双引号。
话说,通过此次重构,将自己前几天看的 kafka 完美的融入了进来,简直美滋滋…
Q2:遇到的第一个大问题,其实还是考虑如何将登录后的界面拿到,因为我后续的操作都是要基于已经登录后的这个标签页的
这的确是一个难题,我这边最后的做法是将 driver 这个chrome的驱动变为一个 static volatile,这样在多线程操作的时候,能够同步 driver 的状态,也就是说,整个 Crawl 类只有一个 driver 实例,而且我用了单例模式下的饿汉模式,直接在第一次初始化的时候就将 driver 进行实例化了,login() 执行的时候是拿到唯一的 driver 实例,然后后期 crawl 的时候,由于是单例化的,所以必然也是拿到同一个 driver,恩,我真是个天才…
Q3:最费时间的还是要对 python 模块进行一个完整的对接
在不改变 python模块的代码的前提下,进行代码的重构,这的确有点浪费时间,尤其是要考虑到 kafka 消息传递的不变,所以可能会比较花费时间吧..
Q4:如何启动爬虫的
我是直接将业务全部写在 Consumer 这个类中了,然后 Crawl 这个类就负责进行登录、爬取等操作,其中,Consumer 类中直接通过线程池调用 Crawl 中的方法,并通过 future.get() 进行结果的获取。
Producer 这个类负责进行任务的发送,而 Utils 则是包含一些工具方法,比如对 keyword 的处理,说到对 keyword 的处理,主要还是要满足 url 编码的规范,所以需要进行一定的处理。
Q5:抓取名字是抓取 html 还是通过 rpc 获取?
经过自己的测试,还是 rpc 的靠谱一些,但是两者都不够靠谱…
1
2
3 > // 1. 通过 rpc,这种方式的好处是当页面一直处于 loading 状态并且无法加载数据时,通过 rpc 反而可以获得数据,坏处就是有的时候页面加载出来了数据但是却拦截不到该请求
> // 2. 直接通过页面抓取我们需要的数据,好处就是不用承担 rpc 可能拦截不到的风险,坏处就是有的时候会 loading,导致抓不到数据
>
感觉最好的方式是:先进行页面的抓取,如果发现是 loading 状态,则转为 rpc 调用,两者都没有数据,说明 no match。
懒得试了…到时候如果要上线,再试试…
Q6: java 中如何使用 webdriver?
http://www.testclass.net/selenium_java
主要是参考这个网址,剩下的看chrome中的 ”其他书签“
Q7:设置 cookie,不需要再登录了
收获
- 对 kafka 和 java 的对接的熟悉,直接将前几天看的全部给用上了,顺带自己写了个自定义的序列化器。
- 线程池、selenium的运用、request的运用,以前都只是在 python 中用,现在感觉在 java 中也同样是十分方便的。
- 自己顺带重写了个 request 有关的工具类,里面有很多实用的工具方法,在 leetcode 文件夹下的 爬虫demo。
- 对业务的再次熟悉,感觉一整套下来,逻辑已经是非常清晰了,我的代码自己觉得写的也是很清晰的,终于不用担心交接的时候坑别人了…
- 最大的收获当然是更加自信了,感觉写起来还是挺简单的,以前花了个把月才熟悉的 node,用 java 写两天不到就搞定了,最终可能这份代码也用不上,但是给自己的信心是实打实的!
还需要做的工作
- 将该工程独立出去,形成一个maven管理的单独的工程
- 跟原来的部分代码对接好,尤其是 topic 不要弄错了 「已完成」
- 加密协议写好 「changze 那边已经写完了」
- 服务器上的某些东西和mac是不一样的,比如 chromeDriver 的地址需要改动,还有就是付费账号是拥有真实姓名,所以在通过keyword的第二种方法获取名字时,className 是有变化的 「了解了」
- 尽量减少谷歌验证出现的次数
- 写一个 ReadMe.txt 「已完成」
好了,项目这块就这样了…
得抓紧时间写一下实验和复习考试科目了…
加油!!!