重构项目代码

前言

趁着五一假期,自己也没出去玩,所以有大把的空闲时间,想到马上实习去了,可能项目要交接,于是自己决定重构一下代码… 因为我是在师兄的代码的基础上进行维护修改的,改到后面真的是越来越复杂,越来越麻烦,以至于现在我随便加点新功能,完全没有可扩展性,而且代码没有任何可读性…我都不知道我是怎么读下去这个代码并且修改的,简直就是在 ”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 「已完成」

好了,项目这块就这样了…

得抓紧时间写一下实验和复习考试科目了…

加油!!!

Thank you for your accept. mua!
-------------本文结束感谢您的阅读-------------