今天接到个需求,一个同学需要我帮忙爬取一下携程的民宿酒店数据。都知道携程难爬,我一不小心就掉坑里了。
其实携程难爬的数据是酒店数据,而这个民宿应该是个新上线的业务,所以并没有做什么反爬手段,可惜老夫不知道啊,所以从中午接到电话就开始了折腾之路。
第一阶段:人生苦短,我用python
刚一听到这个需求,就想用python来做,所以先装python环境,又装了pycharm,找了几个脚本,基本都是跑不起来,要么是库安装不了,要么是语法不对。鉴于本人的渣渣python水平,在捣鼓了一两个小时后放弃了。中间的坑主要是库不对,我cmd窗口安装的库和pycharm的库不是通用的,cmd各种库都能装,pycharm有个别库搜索不到,所以,你懂得。。。
第二阶段:搜索java解决方案
java的方案比较多,这一阶段主要是网上搜索各种demo,找了那么五六个,甚至还在csdn用积分下载了两个,可惜由于代码基本都是去年的,请求的路径还是aspx,最新的携程已经不是这个了,找到的所有的教程都是基于这种方式的,所以根本也都用不了。
ps:中间还用了下*Chrome*driver方案,但教程是爬取艺龙的,能用,放弃。
还有很多教程,没有完整代码,拷贝过来并不能运行,还有几个是广告贴,让买一个什么携程海内外酒店爬虫系统,未付费只能爬十条,可惜注册的页面手机号码都输入不了,放弃。
搞到这个时候,一下午基本已经过去了,这时候同学打电话过来,他已经人肉完了,所以,彻底在他面前丢人了。
其实,一直陷入到了误区中,到了这个阶段,我一直以为携程的很难爬,所以跟小伙伴聊了一下,直接找到请求的地址,拿apidebug进行了测试,看到post请求中十几个请求头,请求参数也是一大堆,弄的真是心力交瘁。最后也测试通过了,证明根据这个路径可以爬,而且他返回的是json数据。此时下班了。。。。
第三阶段:jsoup,webmagic方式
回家后继续折腾,之前用过jsoup爬过医药行业的信息,所有还是按这个思路,各种搭环境,找demo代码,中间也试了webmagic,都差不多。搞到一半突然反应过来了,这两个工具都是解析静态页面的,可老夫不需要解析页面啊,人家携程已经很友好地通过接口返回json数据了,我这还弄个毛的html解析啊,于是,里面又转换思路。
第四阶段:httpclient终极大招
想明白了这个问题,其实就是发送个http请求,然后解析得到的json数据转换成对象,存到数据库就ok了。所以就是最后的直接发送http的post请求阶段,代码如下:
pom依赖:
```html
org.apache.httpcomponents
httpclient
4.3.1
mysql
mysql-connector-java
5.1.34
com.alibaba
fastjson
1.2.31
```
![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)
java实体类
```java
package cn.wanghaomiao;
import java.util.Date;
/**
* @Author: szz
* @Date: 2019/5/29 下午9:50
* @Version 1.0
*/
public class Hotel {
String id;
String pid;
String pname;
String zone;
String lng;
String lat;
String zoneId;
String rname;
Date createTime;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public String getZone() {
return zone;
}
public void setZone(String zone) {
this.zone = zone;
}
public String getLng() {
return lng;
}
public void setLng(String lng) {
this.lng = lng;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;