一、应用宝广告主信息抓取
1.1对应用宝首页的分析
- 进入应用宝首页http://sj.qq.com/,所有应用在应用市场中
- 在应用市场中分成了两层,
- 第二层:在第一层上进行了细分
- 分析其源代码,并没有将所有的应用全部加载出来,进一步分析是利用了ajax异步请求。
1.2请求和响应的分析
- 分析请求,以以下请求作为说明
- 其中
- orgame:1表示工具类应用,2表示游戏类应用
- categoryId:代表的是细节化的分类的id,在分析其请求时,没发现比较明显的规律,所以在抓取时将id记录在了两个列表中,
- lis1=[-10,122,102,110,103,108,115,106,101,119,104,114,117,107,112,118,111,109,105,100,113,116];工具类应用分类id
- lis2=[147,121,149,144,151,148,153,146];#游戏类应用分类id
- pageSize:表示每次请求数量,设置的为20
- pageContext:偏移量。
- 并且响应结果是json格式的数据,以下是一条数据的响应结果
- {"total":1,"count":1,"obj":[{"description":null,"flag":16533,"fileSize":14352335,"authorId":179,"categoryId":119,"categoryName":"美化","apkMd5":"9CB8B24EFFFAFFF2DC64A88104566D1A","apkUrl":"http://imtt.dd.qq.com/16891/9CB8B24EFFFAFFF2DC64A88104566D1A.apk?fsname=com.tencent.qlauncher.lite_2.1.2_64171102.apk&csr=3554","appDownCount":187774441,"appId":12052257,"appName":"微桌面(智能语音主题壁纸美化锁屏)","authorName":"腾讯公司","iconUrl":"http://pp.myapp.com/ma_icon/0/icon_12052257_1509706295/256","newFeature":"1. 修复了一些已知bug修复;\r\n2. 叮当语音助手性能优化;”,”pkgName":"com.tencent.qlauncher.lite","versionCode":64171102,"versionName":"2.1.2","averageRating":4.324552160168598,"editorIntro":"全新一代智能、高效桌面管理软件","images":["http://pp.myapp.com/ma_pic2/0/shot_12052257_1_1509706292/550","http://pp.myapp.com/ma_pic2/0/shot_12052257_2_1509706292/550","http://pp.myapp.com/ma_pic2/0/shot_12052257_3_1509706292/550","http://pp.myapp.com/ma_pic2/0/shot_12052257_4_1509706292/550","http://pp.myapp.com/ma_pic2/0/shot_12052257_5_1509706292/550"],"apkPublishTime":1509706296,"appRatingInfo":{"averageRating":4.324552160168598,"ratingCount":16133,"ratingDistribution":{"1":1926,"2":297,"3":672,"4":958,"5":12280}},"snapshotsUrl":null,"appTags":null}],"pageContext":"","success":true,"pageSize":null,"msg":"success"}
- 对响应结果分析,主要抓取以下几项数据
- appName,应用名称
- authorName,开发商名称
- categoryName,类别名称,但是我们在存储时,并不是直接将抓取到的类别名称进行存储,而是进行了类别映射
dic={
#应用宝中游戏分类:映射标号
'休闲益智':'5014',
'网络游戏':'',
'飞行射击':'',
'动作冒险':'5002',
'体育竞速':'5001',
'棋牌中心':'5014',
'经营策略':'5003',
'角色扮演':'5005',
#应用宝中工具应用分类:映射标号
'购物':'5024',
'阅读':'5074',
'新闻':'5036',
'视频':'5053',
'旅游':'5070',
'工具':'5019,5066',
'社交':'5021',
'音乐':'5053',
'美化':'',
'摄影':'5037',
'理财':'5026',
'系统':'',
'生活':'5023',
'出行':'5070',
'安全':'',
'教育':'5025',
'健康':'5028',
'娱乐':'5020',
'儿童':'',
'办公':'',
'通讯':''
};
- store_url,应用下载链接
- pkgName,包名
- iconUrl,应用图标,需要做cdn处理,目前不太清楚cdn生成方式,只是将图标的url抓取了下来,没有进一步的处理。
- 使用的scrapy框架进行的爬取,爬虫名称appstore
1.3实现逻辑
爬取流程如下:
主要逻辑是在回调函数parse()中实现的,每次在进行数据的获取前都需要对当前状态进行判断
#是否将所有数据抓取完,是则停止抓取
if (json.loads(response.body)['count']==0) and (self.orgame==2) and self.l2 >=len(self.lis2):
return;
#是否将游戏当前分类中的数据抓取完,是则对当前类的下一分类进行抓取
elif (json.loads(response.body)['count']==0) and (self.orgame==2) and self.l2 <len(self.lis2):
self.offset=0;
self.category=self.lis2[self.l2];
self.l2=self.l2+1;
#是否将工具类的数据抓取完,抓取完则置2,开始抓取游戏类的数据
elif (json.loads(response.body)['count']==0) and (self.orgame==1) and self.l1 >=len(self.lis1):
self.orgame=2;
self.offset=0;
self.category=self.lis2[0];
self.l2=self.l2+1;
#是否将工具类当前类数据抓完,抓完则抓下一个分类
elif (json.loads(response.body)['count']==0) and (self.orgame==1) and self.l1 <len(self.lis1):
self.category=self.lis1[self.l1];
self.offset=0;
self.l1=self.l1+1;
#else中是具体的抓取内容
else:
…
需要注意的是在保存类别id时,有可能当前应用的分类并不在已有的分类中,此时需要给一个判断
#如果存在则直接置已有类别标号
if(self.dic.__contains__(data['categoryName'])):
item[‘categoryName']=self.dic[data['categoryName']];
#如果不存在,则置为空
else:
item[‘categoryName']='';
- 持久化处理,就是将抓取到的数据保存到数据库
二、表的迁移
参考 pull_app_profile.py
pull_advertiser(startId, endId);
其实现逻辑结构如下:
三、遇到的问题
1、scrapy框架熟悉中
2、cdn的获取不理解
3、在进行数据持久化处理时,因为是在本地进行的连接,所以访问数据库出了点问题。
4、在分析pull_app_profile.py发现,使用的是peewee库操作数据库,对这个库还不了解
四、后续计划
继续深入学习scrapy框架
熟悉python下操作mysql的常用库
熟悉项目结构