因为公司业务需求,需要获取汽车之家的车型配置数据如下图:

由于汽车之家没做防爬策略,只是数据给混淆了,这里主要说解析数据。

通过保存页面,配置项的数据是通过JS动态生成的。在页面的第572行左右,有配置项的json格式数据

主要的配置数据是config和option,车身颜色color和内部颜色innerColor。一开始以为汽车之家的数据还挺好抓取,直接页面上就有。但是通过格式化工具后发现,配置项的名称和值的部分字,被随机的用span标签加CSS给替换了,例如下面一个:

<span class='hs_kw72_configKE'></span>

那就去页面里面看看有没有.hs_kw72_configKE的CSS样式,然而并没有找到,然后再找找引入的CSS文件里也没有,这就头疼了。最后发现这些用于替代文字的CSS样式是通过JS代码生成的,并且JS代码也在页面中,在保存下来页面中有两行。

上面这个第一部分,下面这个是第二部分,注意第二部分是两个<script></script>块,我这只截取了开头

一开始到这步的时候觉得没戏了,一开始也想着怎么能执行这段JS代码,Java可以执行JS的脚步,但是这些JS脚步里面有浏览器对象,例如document,window等,也尝试着通过Java写这些相关的对象,然后放入JavaScript执行引擎的上下文中,但是没能成功,后来在网上看到七月流光一个相关的文章,也是这个问题,给出了一个比较巧的解决方法(七月流光的博客地址)。他的方法是通过创建几个JS对象替代,脚步执行所需要的对象,包括document和window对象。

var rules = "";
var document = {};
document.createElement = function() {return {sheet: {insertRule: function(rule, i) {if (rules.length == 0) {rules = rule;} else {rules = rules + "|" + rule;}}}}
};
document.getElementsByTagName = function() {};
document.querySelectorAll = function() {return {};
};
document.head = {};
document.head.appendChild = function() {};
var window = {};
window.decodeURIComponent = decodeURIComponent;
window.location = {};
window.location.href = "car.m.autohome.com.cn";

将上面这段JS放到用于生成CSS的JS代码前,然后通过Java的脚步引擎执行这段JS,就能获取到如下结果

把CSS样式破解出来,那么再把上面的json数据里面的span给替换成汉字,再解析json数据就OK了。

但是注意一点,生成CSS的JS代码好像有两种,一种是里面有汉字的,一种里面没汉字,没汉字的Java在执行代码是加上-Xss=5m,否则会报StackOverflowError

Java测试代码如下,用到Jsoup

package cn.iautos.crawler.analysis.util.test;import com.alibaba.fastjson.JSONObject;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.junit.Test;import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** <br/>* Created on 2017/10/13 16:25.** @author zhubenle*/
public class UtilTest {public final static String SCRIPT_PRE = "var rules = '';var document = {};document.createElement = function() {return {sheet: {insertRule: " +"function(rule, i) {if (rules.length == 0) {rules = rule;} else {rules = rules + '|' + rule;}}}}};document.getElementsByTagName = " +"function() {};document.querySelectorAll = function() {return {};};document.head = {};document.head.appendChild = function() " +"{};var window = {};window.decodeURIComponent = decodeURIComponent;window.location = {};window.location.href = 'car.m.autohome.com.cn';";public final static Pattern CSS_PATTERN = Pattern.compile("\\.(.*)::before.*content:\"(.*)\".*");@Testpublic void testScript() throws Exception {String url = "https://car.autohome.com.cn/config/series/692.html";Connection.Response response = Jsoup.connect(url).validateTLSCertificates(false).ignoreContentType(true).ignoreHttpErrors(true).execute();System.out.println(response.statusCode());Document document = response.parse();Elements scripts = document.select("script:containsData(insertRule)");ScriptEngineManager scriptEngineManager = new ScriptEngineManager();ScriptEngine engine = scriptEngineManager.getEngineByName("JavaScript");Map<String, String> cssKeyValue = new HashMap<>();System.out.println("------------css数据------------");scripts.forEach(element -> {String script = SCRIPT_PRE + element.html();try {engine.eval(script);} catch (ScriptException e) {e.printStackTrace();}String css = (String) engine.get("rules");System.out.println(css);for (String str : css.split("\\|")) {Matcher cssMatcher = CSS_PATTERN.matcher(str);if (cssMatcher.find()) {cssKeyValue.put("<span class='" + cssMatcher.group(1) + "'></span>", cssMatcher.group(2));}}});Elements contents = document.select("script:containsData(keyLink)");String content = contents.html();System.out.println("------------用css混淆的配置数据------------");System.out.println(content);//把混淆数据里的样式用上面解析的样式给替代for(Map.Entry<String, String> entry : cssKeyValue.entrySet()) {content = content.replaceAll(entry.getKey(), entry.getValue());}System.out.println("------------用css替换后的数据------------");System.out.println(content);engine.eval(content);System.out.println("------------每个配置结果------------");String keyLink = JSONObject.toJSONString(engine.get("keyLink"));String config = JSONObject.toJSONString(engine.get("config"));String option = JSONObject.toJSONString(engine.get("option"));String bag = JSONObject.toJSONString(engine.get("bag"));String color = JSONObject.toJSONString(engine.get("color"));String innerColor = JSONObject.toJSONString(engine.get("innerColor"));System.out.println(keyLink);System.out.println(config);System.out.println(option);System.out.println(bag);System.out.println(color);System.out.println(innerColor);//最后的数据,解析json就ok}
}

(谢谢,有问题发邮箱联系zhubenle@gmail.com)

使用Java抓取解析汽车之家车型配置数据相关推荐

  1. 用Java抓取10年大乐透中奖数据

    最近突发奇想,想用java拉去最近十年的大乐透中奖数据,然后使用机器学习预测下一期的开奖结果,看看能不能瞬间财务自由,第一步:拉取最近十年的大乐透中奖数据. 首先找个能查询大乐透开奖数据的网站: ht ...

  2. java 开发用到网络爬虫,抓取汽车之家网站全部数据经历

    经历了两个礼拜的折腾,某某知名网站的数据终于到手了.犯罪没被发现这种心情感觉很爽. 说一下我的犯罪经历,之前公司总是抓取某某网站数据,可能是被发现了.某某网站改变了策略.通过各种技术终止了我们的行为, ...

  3. java抓取网站数据

    java 抓取网站数据 假设你需要获取51job 人才网上java 人才的需求数量,首先你需要分析51job 网站的搜索这 一块是怎么运作的,通过解析网页的源代码,我们发现了以下一些信息: 1. 搜索 ...

  4. scrapy汽车之家车型的简单爬取

    汽车之家车型的简单爬取 spider # -*- coding: utf-8 -*- import scrapy from scrapy import Request from mininova.it ...

  5. java 抓取网页乱码_java抓取网页乱码问题的处理

    今天同事做了一个我们感觉很牛B的彩票预测程序,采用的是遗传算法实现,于是我"剽"来学习先,但是部署到我电脑上以后,就有问题了: 1.用她的抓取程序得到的网页内容出现乱码,导致数据无 ...

  6. 学校铃声Java_java_java多线程抓取铃声多多官网的铃声数据,一直想练习下java多线程抓取数 - phpStudy...

    java多线程抓取铃声多多官网的铃声数据 一直想练习下java多线程抓取数据. 有天被我发现,铃声多多的官网(http://www.shoujiduoduo.com/main/)有大量的数据. 通过观 ...

  7. Java抓取起点小说输出到本地文件夹和数据库

    Java抓取起点小说输出到本地文件夹和数据库 目录 项目结构 所需插件 项目代码 输出结果 目录 项目结构 第一次写网络爬虫,参考了别人的,也自己理解了用法 所需插件 因为使用了mevan,直接上po ...

  8. Java爬取解析去哪儿景点信息

    前言:这两周在做 Web 课的大作业,顺便琢磨了一下如何使用 Java 从网上获取一些数据,现在写这篇博客记录一下. PS:这里仅限交流学习用,如利用代码进行恶意攻击他网站,和作者无关!!! Java ...

  9. java抓取网页内容

    今天做项目时用到java抓取网页内容,本以为很简单的一件事但是还是让我蛋疼了一会,网上资料一大堆但是都是通过url抓取网页内容,但是我要的是读取本地的html页面内容的方法,网上找不到怎么办我瞬间了! ...

  10. java抓取网页数据_简易数据分析 10 | Web Scraper 翻页——抓取滚动加载类型网页...

    [这是简易数据分析系列的第 10 篇文章] 友情提示:这一篇文章的内容较多,信息量比较大,希望大家学习的时候多看几遍. 我们在刷朋友圈刷微博的时候,总会强调一个『刷』字,因为看动态的时候,当把内容拉到 ...

最新文章

  1. numpy中矩阵运算的特点
  2. 关于eclipse的一些简单配置
  3. 22 PP配置-生产车间控制-定义工单类型
  4. android php 项目代码混淆,Android Studio配置反混淆的实现
  5. python如何使数据加行_如何使用 Python 插入行
  6. sql中常见sqlcode原因分析
  7. 为什么手机发射功率这么小而基站却能收到信号?
  8. Redis Lpush 命令
  9. Feed Ratios
  10. Habor镜像仓库的使用
  11. 用while输出1到100的偶数python_用while语句,求1到100的偶数之和
  12. java模拟器怎么打开apk文件,APK是什么 APK文件怎么打开【详解】
  13. Java线程池设置多少线程合适
  14. OkHttp3——连接池
  15. python种子下载器,tkinter版本
  16. 如何去除CSDN博客图片水印
  17. Mac无法找到摄像头问题解决
  18. 笔记本出现数字小键盘怎么解决,出现方形带斜杠123
  19. C语言实现生成BMP图片文件(BMP文件格式,二进制文件读写)
  20. 絮叨絮叨看护机房之监控

热门文章

  1. Java 数据库基本操作
  2. 手游方舟怎么输入代码_单机方舟不能输入代码怎么回事 | 手游网游页游攻略大全...
  3. HackerRank做题
  4. 恒生O32系统的前世今生
  5. 郝斌数据结构与算法自学视频教程
  6. cpc客户端网络不通
  7. 计算机毕业设计之流浪宠物管理系统
  8. 使用nginx 和 switchhost实现自定义域名指向本地服务
  9. mysql基本语法 外键_MySQL语法创建外键?
  10. 设计(二) | PS功能快捷键(全)