链家小区坐标爬取

之前已经爬取了链家小区的一些基本信息,主要是列表里的内容。但是这里面没有我最需要的数据之一:小区坐标,于是开始重新找。 首先发现小区详情页面是有地图的,根据经验,如果有地图的定位,在页面上肯定有坐标。地图是百度地图,正好是我需要的百度经纬度坐标体系。 自己找的时候走了一些弯路,但是我觉得这也应该是没有经验的情况下的正确查找路子。 我是首先打开开发者页面,然后看点击地图的时候发起的请求,点击地图,放大缩小,看发起的请求里有没有坐标。遗憾的是没能找到,也许是我漏掉了。但是我知道页面一定有,否则这里调用地图的api进行定位的时候显然是不行的。 在我查看源码,从详情页整理小区数据的时候,偶然看到,我不需要的一部分数据里:附近门店 的信息里,隐藏着小区的坐标。如下图所示

很开心,这么容易就找到了。 于是写代码,将这部分数据洗出来,代码如下: countStr = locationInfoItem.selectFirst(“span[class=xiaoquInfoContent]”).text();String locationInfo = locationInfoItem.selectFirst(“span[class=xiaoquInfoContent]”).selectFirst(“span[class=actshowMap]”).attr(“xiaoqu”); locationInfo = locationInfo.replace(“[“, “”).replace(“]”, “”); entity.setLocationJingDu(locationInfo.split(“,”)[0]);entity.setLocationWeiDu(locationInfo.split(“,”)[1]);由于前面已经跑完小区的基本信息了,小区详情页面的地址也已经保存下来了,于是直接把这些数据重新跑一遍,根据详情页面爬取坐标数据,以为于是就完事儿了 然而,到最后发现,总是有那么百十个小区,解析总是失败的。观察日志,发现请求是正常的并且成功的,如果是被反爬虫了按照我这换ip的频率,也不应该一直失败的,肯定代码原因咯。 没办法,debug大法。调试到获取坐标这块的时候,异常了,仔细观察发现,有的小区是没有附近的门店的!没有的时候,我的解析坐标的部分就会异常。 那咋办?找到一个正常的页面,然后找到附近门店那里的坐标数字,然后全页面搜索,果然不服所望,还有个地方存着坐标!如图所示

然后到没有附近门店的页面去验证,果然也有!这下好了。 改代码对 附近门店 这里做个判断,如果是  暂无门店信息 ,那就去找js标签,然后从中提取坐标。因为比较好找,我的数据又比较少,懒得用正则了,直接split完事儿。上代码 Elements scriptElements = doc.select(“script”); String shopLatLng = “”; for (Element element : scriptElements) {    shopLatLng = element.html();    if (shopLatLng.contains(“resblockPosition”)) {       break;    } }shopLatLng = shopLatLng.split(“require\\(\\[‘ershoufang/xiaoquDetail/index’], function\\(main\\) \\{\n” +”  main\\(“)[1].split(“\\);\n” +”\\}\\);”)[0]; ResBlock resBlock = JsonUtil.of(shopLatLng,ResBlock.class); Optional.ofNullable(resBlock).ifPresent(x->{   entity.setLocationJingDu(x.getResblockPosition().split(“,”)[0]);    entity.setLocationWeiDu(x.getResblockPosition().split(“,”)[1]); });至此,获取小区坐标就完成了,然后顺利跑完交差。

链家小区数据爬取

这次爬取链家数据时爬取的链家北京区域的所有小区数据。
区域比较少,手动去把每个区的列表页面罗列了出来(所有分区全家起来288个)
没有去处理当前总共多少页,之类的数据,而是把这个数据导入到一张表里,表字段设计了页数和当前爬取的页码,这样方便重试,也不做无用功跑已经跑过的数据。
由于一开始只需要小区的名称,地址,当前均价等,这些信息都有了,所以也没有去爬详情。
列表页面的URL格式为:https://bj.lianjia.com/xiaoqu/guangqumen/
默认为第一页,首页之后的格式均为在当前URL后面添加 pg+pageNo+/ 。
String realUrl = baseUrl + “pg” + pageNo + “/”;
通过写好的可以使用代理的HttpClient发起请求,列表页还是很容易请求成功的。
然后使用Jsoup解析请求到的网页字符串(据大神说,用XPath更高端更牛皮,不过我用着Jsoup还很顺手,就暂时不换了 – 主要以前用jquery习惯,所以找起来也方便)
import org.jsoup.Jsoup;
Document doc = Jsoup.parse(html);
打开网页调试工具,找到翻页位置的元素,发现:翻页的所有链接都在li[class=house-lst-page-box]元素内的超链接标签<a>上,并且最后一个超链接标签就是最大页码的标签,标签上的属性 data-page 就是页码,也就是最大页数,正好提取出来
代码:
Elements pageList = doc.select(“li[class=house-lst-page-box]”).select(“a”);
Element a = Safes.first(Lists.reverse(pageList));
Integer pageCount = Integer.valueOf(a.attr(“data-page”));
至此最大页数和当前页都已经拿到了。接着是收集小区信息。
小区列表中每个小区的信息就在一堆class=xiaoquListItem的li元素里,包含了列表里需要的所有小区的信息,先把每个小区的块都拿到。(当时爬的时候,下面填充用的标签还用的是a标签,写文章时候已经改成div和a标签交叉的了,感觉链家也不是没有做反爬虫,只是做的比较简单,下面呈上原来的老代码)
ElementsxiaoquList=doc.select(“li[class=xiaoquListItem]”).select(“a”).select(“a[class=PageLink]”)
接下来看源码就比较清楚了,里面分了三大块,左侧是图片,中间是小区名称、最近的成交信息、地址信息、代理人信息和标签信息,放在class=info的div里,每一块信息是一个div,右侧是价格、在售信息等内容,放在class=xiaoquListItemRight的div里。
从里面分别取出来这些信息,并放到对应对象里
List<LianJiaXiaoquEntity> entityList = Lists.newArrayList();
Safes.of(xiaoquList).forEach(xiaoqu -> {
    LianJiaXiaoquEntity entity = new LianJiaXiaoquEntity();
    Element title = Safes.first(xiaoqu.select(“div[class=title]”)).selectFirst(“a”);
    entity.setName(title.text());
    entity.setUrl(title.attr(“href”));
    Optional.ofNullable(Safes.first(xiaoqu.select(“div[positionInfo]”))).ifPresent(positionInfo -> {
        positionInfo.text();// \r\n&nbsp;\r\n&nbsp;/板楼/塔板结合/r/n&nbsp;2002年建成
        entity.setNameDetail(StringUtils.join(positionInfo.select(“a”).stream().map(Element::text).collect(Collectors.toList()), “-“) + entity.getName());
    });
    Optional.ofNullable(Safes.first(xiaoqu.select(“div[class=xiaoquListItemRight]”))).ifPresent(price -> {
        entity.setAveaPrice(Safes.first(price.select(“span”)).text());
        entity.setPriceTime(Safes.first(price.select(“div[class=priceDesc]”)).text());
    });
    entityList.add(entity);
这样,就把列表里一些小区的基本信息保存下来了。
但是我需要的不只是这些,主要还需要小区的坐标,这个在列表里没有。找小区坐标的过程也是一波三折,接下来说。