一个数据采集系统(通俗的说就是爬虫),用来采集 58同城 房产 | 郑州中的房屋数据。使用 Java 语言和Jsoup库编写,这里分享给大家。
最后采集的数据结果 CSV 文件保存的,如下所示
说明
功能都集中在 spider.get58 包的如下4个类中:
- App: 应用驱动程序,控制爬虫的启动/运行逻辑和日志打印等;
- CrawUtil: 爬虫爬取单元,爬取特定的 url 返回 html 对象;
- DomParse: 从 html dom 中解析出需要的数据;
- House: Pojo,存储需要的数据信息。
用到的 Maven 依赖如下:
<dependency>
<!-- jsoup HTML parser library @ https://jsoup.org/ -->
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.12.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.61</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
CrawUtil 的功能/实现是什么?
使用 Java 的 Jsoup 库(一个 Java 领域的爬虫库,相当于 python 中的 requests和 beautifulsoup)给定一个 url 连接,返回其 HTML,也就是 Jsoup库 中的 org.jsoup.nodes.Document 对象。这其中可以增加一些反反爬虫策略,如添加代理池、user-agent 标识等,来避免被人机验证。
DomParse 做了什么?
用来解析从 CarwUtil 中得到的 Document 对象,从中一步一步地遍历 dom 节点找出自己所需要的数据,这个过程就是自己现在浏览器的控制台中逐个寻找自己目标数据的位置(就像下图那样),然后通过一系列 Java API 操作得到这些数据,最后把它们额外处理下返回。里面提供了不同的方法,对应于从不同的信息网页解析出特定数据。
House 里面都包含了什么数据?
这里的数据都是58同城的网页上提供的,具体属性可以看后面的源码。
App 驱动都做了什么?
这个是代码中的核心部分,它控制了程序井井有条地爬取了58同城中所有的房屋数据,以及如何处理58的人机验证。要想详细解释它,我必须先解释下我是如何处理反爬虫的。我手工破的😂
我是如何处理反爬虫/人机验证的?
IP 代理池?我并没有这么做,因为我没有找到可靠的代理服务,因此我的解决方案是在我单机/单IP跑的情况下的;另外,众所周知,58同城 的反爬虫做的是很严格的,很容易出现人机验证。我觉得我做的并不是很好🤦🤦🤦 因为它很耗时,虽然可以保证顺利运行。
增加爬取两个URL间的时间间隔,随机 1 - 5 秒这个范围。这样并不能保证你一定不会被人机验证,但可以保证被人机验证的频率很低。
人机验证对我来说是肯定会出现的,只要出现,程序就无法进行运行,一来 URL 无法正常访问,二来 DomParse 解析是会造成 空指针异常而退出程序。所以我写了一个机制,能够保证异常退出后再次运行能接着上次错误的地方从新开始。(这次运气比较差,没爬了几个就给人机验证了🤦)
第一步,我先爬取并保存了所有房屋页面 的 URL列表,以 json array 保存到本地 url-list.json中,如下图所示:
包含了 url 的 id 信息(对应于第几个)、url 链接、总价和单价,第一个 url 是 https://zz.58.com/ershoufang/41737908848774x.shtml?utm_source=&spm=&cityListName=zz&curListName=zz&referinfo=FALSE&typecode=201,你可以打开看看,这些数据来自这个网页 https://zz.58.com/ershoufang/pn1/,array 中每个 object 对应如下:(PS:这些数据的排序并不并保证每次点开都一致)
依次采集完 30个 页面的 URL 列表。
第二步,根据 url-list.json,依次采集里面所有的 URL 数据(事实上它会从 failed-mark.json(下面会介绍)里标记的 id 开始)。
第三步,如果碰到人机验证出现空指针异常导致程序退出,那么点开失败的 url ,手动进行人机验证😂😂😂。
第四步,异常退出时,程序会自动生成一个错误文件 failed-mark.json,里面标记了失败的 url 信息,这样手动人机验证后,再次启动 程序时,程序会接着上次失败的地方继续开始。