使用Java做爬虫时遇到的几个坑

写在前面

最近项目里边需要在Java中使用爬虫技术,原本打算用python写好爬虫然后用Java来调用,但是在网上找了许多Java调用python代码的方法,发现其中的用法都十分重量级,要不就把Jython解释器整个弄来,要不就直接在命令行运行python文件,这都不是我想要的。权衡再三后决定用Java把爬虫重新实现一遍,不得不说,语言和语言之间的区别不是一点半点。下面是我在代码移植过程中遇到的几个坑:

javax.script包解析JS时出现的问题

要爬的网站在数据加密方面下了功夫,用户请求得到的数据都是密文,需要网站自带的JS代码进行解密,千辛万苦把用来解密的JS代码扒出来后,使用python的execjs包完美运行~~将代码移植到Java上的时候,百度发现Java中有专门用来解析脚本文件的javax,script包,兴冲冲的直接用上,一运行,我蒙了,控制台飘红,JS运行出错了:

t.slice is not a function

吓得我赶紧看了看JS代码,没错啊,在python上完美运行的也是这代码,怎么换到Java上就不行了呢??
命名冲突?我赶紧把同名的变量全部改了名字,又用python运行了一遍,能够正常运行,再转到Java,期待能够解决,没料想不但没有解决,错误还多了几行…
本来就没有什么js经验的我顿时慌了阵脚,赶紧百度看看相关问题别人是怎么解决的,结果网上也多是一些牛头不对马嘴的回答,几个小时就这么过去了,后来突然想到,会不会是t这个对象真的没有slice函数,但是不对啊,python上边都能运行,后边我还试了nodejs也一样能运行,怎么这里就不行了?但是我还是抱着试一试的心态搜了一下,原来还真有这么个说法,原来t这个对象的类是Uint8Array,其中的slice函数在某些环境下无法使用(比如安卓),但是他有一个替代函数subarray,可以完成相同的工作。把出错的地方的slice函数换为subarray之后代码运行成功…我也终于舒了一口气,谁能想到是这么个问题…话说为什么要实现两个功能一样的函数…难道是函数别名这种说法??

JS与Java交互的问题

这之后我还犯了一个非常蠢的错误,js代码中直接把js对象返回到java里边了,自己又不知道在Java中怎么解析这个js对象,于是疯狂的在网上找Java解析JSONObject的方法,结果都是通过JSON字符串来创建的JSONObject…我又不知道该怎么办了,后来发现原来js中可以直接把JS对象转换成JSON字符串的函数

JSON.stringify(value[, replacer[, space]])

看到这个函数之后直接想吐槽自己之前都在干嘛…(不过python与js交互的确没有这种步骤,js对象可以直接转换为python中的字典或者列表,它们俩相性真不是一般的好…)

Jsoup保留换行符问题

Jsoup是Java中的一个HTML解析包,其功能非常强大…所谓的soup,我觉得跟python中的BeautifulSoup有异曲同工之妙。不得不说,Jsoup获取的HTML内部文本格式非常美丽,使用过python爬虫的人知道,获取内部文本的方法一般都是text(),而这种方法返回的一般都是不加修饰的字符串或者字符串列表,其中乱七八糟的换行符制表符一大堆,十分影响观感。而Jsoup就不会有这种问题,使用Jsoup提取文本,数据与数据之间使用一个小巧的空格隔开,十分优美,得到的字符串整洁干净,使人赏心悦目。我一边欣赏着提取到的美丽的字符串,一边按下debugger中的下一步,程序运行到下一个断点,这时我发现了一个问题:

我之前写好的正则表达式匹配不到东西了。。。

再确认正则表达式语法上没有出问题之后,我又看了看那优美的字符串,这时,我发现了问题的所在,我感觉有一个巨大的巴掌反复抽打着我的脸:

这个字符串没有换行符

什么意思?由于要爬的页面HTML结构的特殊性,我需要用到换行符\n对数据进行分段,但是Jsoup提取到的数据里边,竟然**没有换行符!!**不得不说Jsoup的这个功能真是华而不实,直接把数据的结构性给破坏了,这可坏事了,怎么办呢…
百度得到了答案:

Jsoup.clean(html, "", Whitelist.none(), new Document.OutputSettings().prettyPrint(false));

使用Jsoup.clean方法,并将最后一个参数设置为new Document.OutPutSettings().prettyPrint(false),于是得到的字符串里边就包含换行符了。

至此,将爬虫从python转移到Java成功,万岁!!!

你可能感兴趣的:(个人笔记)