java 爬取 flash 里面的数据

背景

最近公司需要抓取中国农业信息网(http://jgsb.agri.cn/controller?SERVICE_ID=REGISTRY_JCSJ_MRHQ_SHOW_SERVICE&recordperpage=15&newsearch=true&login_result_sign=nologin) 的数据。在 google 浏览器使用 F12 查看可以发现价格行情数据是嵌套在一个 flash 中的,点击下一页请求服务器,可以看到返回的数据格式是 application/x-amf ,浏览器无法正常解析该数据,接下来就需要用的抓包工具 charles(下载地址 : https://www.charlesproxy.com/download/) 了。

处理

运行抓包工具,在该页面点击 下一页,charles 中效果如图 :

在这里插入图片描述

可以看到比较重要的一些请求封装,然后就是使用 java 模拟 amf 请求了。

maven 依赖

        <!-- https://mvnrepository.com/artifact/org.apache.flex.blazeds/flex-messaging-core -->
        <dependency>
            <groupId>org.apache.flex.blazeds</groupId>
            <artifactId>flex-messaging-core</artifactId>
            <version>4.7.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.flex.blazeds/flex-messaging-common -->
        <dependency>
            <groupId>org.apache.flex.blazeds</groupId>
            <artifactId>flex-messaging-common</artifactId>
            <version>4.7.2</version>
        </dependency>

封装请求

封装请求就是图中框起来的 content 部分。特别注意图中标红得两个包名,这里请求里面封装的包名必须对应起来。

com.itown.kas.pfsc.report.po.HqPara 对象 :

注意这里的包名必须和抓包里面的包名对应起来。

package com.itown.kas.pfsc.report.po;

import lombok.Data;


/**
 * HqPara
 *
 * @author xh
 * @date 2020/5/19
 */
@Data
public class HqPara {

    private String breedInfoDl;
    private String provice;
    private String breedInfo;
    private String marketInfo;

}

封装 content 数据 :

    public static RemotingMessage getRemotingMessage() {
        // content 数组中的第一个对象
        RemotingMessage remotingMessage = new RemotingMessage();
        // 对应对象里面的各个参数
        remotingMessage.setSource(null);
        remotingMessage.setOperation("getHqSearchData");
        remotingMessage.setTimeToLive(0);
        remotingMessage.setTimestamp(0);
        Map<String, Object> headers = new HashMap<>();
        headers.put("DSId", UUID.randomUUID().toString());
        headers.put("DSEndpoint", null);
        remotingMessage.setHeaders(headers);
        // 对应对象里面的 body 对象
        // 数组中的第一个元素 new HqPara() ==> 对应该网页的搜索数据
        // 注意 HqPara 的包名必须对应起来,如果要搜索数据的话,在这个对象中 set 对应的值即可
        // 数组的第二个参数表示当前页
        // 数组的第三个参数表示每页大小
        // 注意合理有个坑!!!
        // 分页数据在请求中是字符串类型,这里也一定要用字符串类型,如果用 int 类型的话,结果是没有值的!!!!
        Object[] body = new Object[]{new HqPara(), "1", "15"};
        remotingMessage.setBody(body);
        remotingMessage.setClientId(UUID.randomUUID().toString());
        remotingMessage.setDestination("reportStatService");
        remotingMessage.setMessageId(UUID.randomUUID().toString());
        return remotingMessage;
    }

返回数据

抓包返回数据大概如下:

在这里插入图片描述

需要的具体数据大概是这样的 :

在这里插入图片描述

编写代码

import com.itown.kas.pfsc.report.po.HqPara;
import flex.messaging.io.ArrayCollection;
import flex.messaging.io.amf.ASObject;
import flex.messaging.io.amf.client.AMFConnection;
import flex.messaging.messages.RemotingMessage;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * SwfApp3
 *
 * @author xh
 * @date 2020/5/19
 */
public class SwfApp {

    public static void main(String[] args) throws Exception {
        String url = "http://jgsb.agri.cn/messagebroker/amf";
        RemotingMessage remotingMessage = getRemotingMessage();
        AMFConnection connection = new AMFConnection();
        connection.addHttpRequestHeader("Content-Type", "application/x-amf");
        connection.connect(url);
        connection.addAmfHeader("DSId", UUID.randomUUID().toString().replaceAll("-", ""));
        // 这里必须和返回值的包名对应起来
        // 这个包可以不用创建
        AMFConnection.registerAlias("DSK", "com.itown.kas.pfsc.report.po.PAuditMarketPrice");
        // call 方法的 command 对应请求中的 Target
        Object call = connection.call(null, remotingMessage);
        
        // 解析返回值
        // flex.messaging.messages.AcknowledgeMessage
        flex.messaging.messages.AcknowledgeMessage message = (flex.messaging.messages.AcknowledgeMessage) call;
        ArrayCollection body = (ArrayCollection) message.getBody();
        ArrayCollection data = (ArrayCollection) body.get(0);
        for (Object column : data) {
            ASObject asObject = (ASObject) column;
            System.out.println(asObject);
        }
        Object curPage = body.get(1);
        Object totalPage = body.get(2);
        Object totalCount = body.get(3);
        System.out.println(curPage + " == " + totalPage + " == " + totalCount);
    }

    public static RemotingMessage getRemotingMessage() {
        // content 数组中的第一个对象
        RemotingMessage remotingMessage = new RemotingMessage();
        // 对应对象里面的各个参数
        remotingMessage.setSource(null);
        remotingMessage.setOperation("getHqSearchData");
        remotingMessage.setTimeToLive(0);
        remotingMessage.setTimestamp(0);
        Map<String, Object> headers = new HashMap<>();
        headers.put("DSId", UUID.randomUUID().toString());
        headers.put("DSEndpoint", null);
        remotingMessage.setHeaders(headers);
        // 对应对象里面的 body 对象
        // 数组中的第一个元素 new HqPara() ==> 对应该网页的搜索数据
        // 注意 HqPara 的包名必须对应起来,如果要搜索数据的话,在这个对象中 set 对应的值即可
        // 数组的第二个参数表示当前页
        // 数组的第三个参数表示每页大小
        // 注意合理有个坑!!!
        // 分页数据在请求中是字符串类型,这里也一定要用字符串类型,如果用 int 类型的话,结果是没有值的!!!!
        Object[] body = new Object[]{new HqPara(), "1", "15"};
        remotingMessage.setBody(body);
        remotingMessage.setClientId(UUID.randomUUID().toString());
        remotingMessage.setDestination("reportStatService");
        remotingMessage.setMessageId(UUID.randomUUID().toString());
        return remotingMessage;
    }

}

运行效果

在这里插入图片描述

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值