爬取基于Flex技术的网站数据

参考:https://github.com/LouisYZK/ShiXi_inWuhan/tree/master/1.23python

Flex技术是网站运用flash方法与客户端进行数据通讯,数据的格式能够是txt,json或amf等。 
AMF是一种二进制编码方式,其在flash传输效率高,以农业信息网数据为例,爬取的方式与通常ajax分析相同。经过抓包分析请求头和响应数据,而后构造请求、接受返回数据git

经过爬取全国农产品批发市场价格信息系统,获取数据,可是此网站是经过flash展现数据,与如今大部分网站展现数据的方法不一样,所以使用python下的pyamf来帮助咱们获取数据。github

1.分析网页

经过分析网页,咱们获得信息,此网站的data是在hqapp.swf中ajax

2.分析请求包json

目前Chales抓包工具可以支持将AMF编码解析成明文形式,便于咱们分析。并发

经过chares抓包,咱们发现请求的body包含一个com.itown.kas.pfsc.report.po.HqPara对象和四个参数,结合网页可知为flash上的四个选择菜单,能够选择省份和批发市场名称等。app

 

class HqPara:
    def __init__(self):
        self.marketInfo = None
        self.breedInfoDl = None
        self.breedInfo = None
        self.provice = None
# 第一个是查询参数,第二个是页数,第三个是控制每页显示的数量(默认每页只显示15条)但爬取的时候能够一会儿设置成所有的数量
# 构造请求数据
def getRequestData(page_num,total_num):
    # 注册自定义的Body参数类型,这样数据类型com.itown.kas.pfsc.report.po.HqPara就会在后面被一并发给服务端(不然服务端就可能返回参数不是预期的异常Client.Message.Deserialize.InvalidType)
    pyamf.register_class(HqPara, alias='com.itown.kas.pfsc.report.po.HqPara')
    # 构造flex.messaging.messages.RemotingMessage消息
    msg = messaging.RemotingMessage(messageId=str(uuid.uuid1()).upper(),
                                    clientId=str(uuid.uuid1()).upper(),
                                    operation='getHqSearchData',
                                    destination='reportStatService',
                                    timeToLive=0,
                                    timestamp=0)
    msg.body = [HqPara(),str(page_num), str(total_num)]
    msg.headers['DSEndpoint'] = None
    msg.headers['DSId'] = str(uuid.uuid1()).upper()
    # 按AMF协议编码数据
    req = remoting.Request('null', body=(msg,))
    env = remoting.Envelope(amfVersion=pyamf.AMF3)
    env.bodies = [('/1', req)]
    data = bytes(remoting.encode(env).read())
    return data
# 返回一个请求的数据格式

2.分析response

能够看到返回的response中,包含有全部记录条数ide

def getResponse(data):
    url = 'http://jgsb.agri.cn/messagebroker/amf'
    req = Request(url, data, headers={'Content-Type': 'application/x-amf'})
    # 解析返回数据
    opener = urllib2.build_opener()
    return opener.open(req).read()

def getContent(response):
    amf_parse_info = remoting.decode(response)
    # 数据总条数
    total_num = amf_parse_info.bodies[0][1].body.body[3]
    info = amf_parse_info.bodies[0][1].body.body[0]
    return total_num, info

3.解析和存储

def storagejson(info):
    path='info.json'
    path1='E:\spyderdata\\'
    res = []
    for record in info:
        record['reportDate'] = record['reportDate'].strftime('%Y-%m-%d %H:%M:%S')
        record['auditDate'] = record['auditDate'].strftime('%Y-%m-%d %H:%M:%S')
        record['snatchDate'] = 'null'
        res.append(record)
    fp = open(path,'w',encoding='utf-8')
    json.dump(res,fp,indent=4,ensure_ascii= False)
    fp.close()
    os.rename(path,path1+filename+path)

if __name__ == '__main__':
    filename = time.strftime("%Y-%m-%d", time.localtime())
    # 第一次请求时,获取数据量
    reqData = getRequestData(1,2)
    rep = getResponse(reqData)
    total_num,info = getContent(rep)
    # 一次请求完成
    reqData = getRequestData(1, total_num)
    rep = getResponse(reqData)
    total_num,info = getContent(rep)
    storagejson(info)

全部代码

from urllib import request as urllib2
from urllib.request import Request
import uuid
import pyamf
import json
import time
import os
from pyamf import remoting
from pyamf.flex import messaging

class HqPara:
    def __init__(self):
        self.marketInfo = None
        self.breedInfoDl = None
        self.breedInfo = None
        self.provice = None
# 第一个是查询参数,第二个是页数,第三个是控制每页显示的数量(默认每页只显示15条)但爬取的时候能够一会儿设置成所有的数量
# 构造请求数据
def getRequestData(page_num,total_num):
    # 注册自定义的Body参数类型,这样数据类型com.itown.kas.pfsc.report.po.HqPara就会在后面被一并发给服务端(不然服务端就可能返回参数不是预期的异常Client.Message.Deserialize.InvalidType)
    pyamf.register_class(HqPara, alias='com.itown.kas.pfsc.report.po.HqPara')
    # 构造flex.messaging.messages.RemotingMessage消息
    msg = messaging.RemotingMessage(messageId=str(uuid.uuid1()).upper(),
                                    clientId=str(uuid.uuid1()).upper(),
                                    operation='getHqSearchData',
                                    destination='reportStatService',
                                    timeToLive=0,
                                    timestamp=0)
    msg.body = [HqPara(),str(page_num), str(total_num)]
    msg.headers['DSEndpoint'] = None
    msg.headers['DSId'] = str(uuid.uuid1()).upper()
    # 按AMF协议编码数据
    req = remoting.Request('null', body=(msg,))
    env = remoting.Envelope(amfVersion=pyamf.AMF3)
    env.bodies = [('/1', req)]
    data = bytes(remoting.encode(env).read())
    return data
# 返回一个请求的数据格式

def getResponse(data):
    url = 'http://jgsb.agri.cn/messagebroker/amf'
    req = Request(url, data, headers={'Content-Type': 'application/x-amf'})
    # 解析返回数据
    opener = urllib2.build_opener()
    return opener.open(req).read()

def getContent(response):
    amf_parse_info = remoting.decode(response)
    # 数据总条数
    total_num = amf_parse_info.bodies[0][1].body.body[3]
    info = amf_parse_info.bodies[0][1].body.body[0]
    return total_num, info

def storagejson(info):
    path='info.json'
    path1='E:\spyderdata\\'
    res = []
    for record in info:
        record['reportDate'] = record['reportDate'].strftime('%Y-%m-%d %H:%M:%S')
        record['auditDate'] = record['auditDate'].strftime('%Y-%m-%d %H:%M:%S')
        record['snatchDate'] = 'null'
        res.append(record)
    fp = open(path,'w',encoding='utf-8')
    json.dump(res,fp,indent=4,ensure_ascii= False)
    fp.close()
    os.rename(path,path1+filename+path)

if __name__ == '__main__':
    filename = time.strftime("%Y-%m-%d", time.localtime())
    # 第一次请求时,获取数据量
    reqData = getRequestData(1,2)
    rep = getResponse(reqData)
    total_num,info = getContent(rep)
    # 一次请求完成
    reqData = getRequestData(1, total_num)
    rep = getResponse(reqData)
    total_num,info = getContent(rep)
    storagejson(info)
View Code

 

遇到的问题:

1.pyamf工具

这次爬虫要用到python的pyamf库,anaconda中并无这个库,所以得本身下载,经过查询得知能够经过pip安装flex

pip install PyAMF

可是安装过程出现错误,没法安装,因而经过下载源文件,解压到  python安装目录\Lib\site-packages下,更名为pamf,在pycharm中导入pyamf,便可使用。

网上搜索时,有人说pyamf不支持python3,须要替换为Py3AMF,可是实测pyamf在python3能够运行爬虫。

相关文章
相关标签/搜索