uni-app+微信小程序+云开发 爬取必应首页每日图片

1.页面与接口数据分析

首先第一步,我们打开bing首页国内版https://cn.bing.com/?FORM=BEHPTB;随手打开F12

经过分析可得到获取图片的 接口是
https://cn.bing.com/HPImageArchive.aspx?format=js&idx=2&n=1&nc=1597026531683&pid=hp&FORM=BEHPTB
返回的数据是

{
	"images": [{
		"startdate": "20200807",
		"fullstartdate": "202008071600",
		"enddate": "20200808",
		"url": "/th?id=OHR.LosOrganos_ZH-CN5283582047_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp",
		"urlbase": "/th?id=OHR.LosOrganos_ZH-CN5283582047",
		"copyright": "鸟瞰戈梅拉岛上管风琴形状的玄武岩,西班牙加那利群岛 (© Martin Siepmann/Image BROKER/Offset by Shutterstock)",
		"copyrightlink": "/search?q=%e6%88%88%e6%a2%85%e6%8b%89%e5%b2%9b&form=hpcapt&mkt=zh-cn",
		"title": "",
		"quiz": "/search?q=Bing+homepage+quiz&filters=WQOskey:%22HPQuiz_20200807_LosOrganos%22&FORM=HPQUIZ",
		"wp": true,
		"hsh": "ec8d73ceb4d3cdfc6dab5681de21eabe",
		"drk": 1,
		"top": 1,
		"bot": 1,
		"hs": []
	}],
	"tooltips": {
		"loading": "正在加载...",
		"previous": "上一个图像",
		"next": "下一个图像",
		"walle": "此图片不能下载用作壁纸。",
		"walls": "下载今日美图。仅限用作桌面壁纸。"
	}
}
然后我们切换图片,分析一下参数和返回数据的变化

可以看出接口的参数变化的是idxnc, 其中idx的可选范围是0-7,说明我们每天可以通过该接口获取8张图片;nc参数的值猜测便知是new Date().getTime()得到,其他参数固定.

然后分析一下返回的数据。切换图片可以发现其实变化的是背景图background-image: url("/th?id=OHR.LassenPeak_ZH-CN5435067682_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp");
这时候就会一眼看出,这个背景图的url 不就是返回的images[0].url`嘛,so嘎 。

2.梳理实现思路

后端

云开发端需要的就是启用微信云函数每天定时调用这个接口;然后呢,把获取到的图片数据;存入微信小程序的json数据库啦。

前端

小程序的前端页面需要做的就是调用云函数获取图片数据以及展示数据

3.代码实现

思路理清楚之后;就是代码的一步步实现了。
接下来话不多说 直接上码

// 云函数入口文件 index.js
const env = 'test'
// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({
  env
})
const db = cloud.database({
  env
})
let preFix = 'https://cn.bing.com'
const fetch = require('./fetch')
async function getBingImg(params = {}) {
  return fetch({
    url: `${preFix}/HPImageArchive.aspx?format=js&n=1&pid=hp&FORM=BEHPTB`,
    params,
    method: 'get',
    timeout: 3000,
    // headers: {
    // }
  })
}
async function getImg(params = {}) {
  const wxContext = cloud.getWXContext()
  let stop = false
  let idx = 0
  let count = 0
  while (!stop) {
    let res = await getBingImg({
      idx: idx,
      nc: new Date().getTime()
    })
    idx ++
    if(res && res.images && res.images.length) {
      try {
        let data = res.images[0]
        // 将获取的数据保存到数据库commonImageList
        let res2 = await cloud.callFunction({
          name: 'addDataToCloud',
          data: {
            dbName: 'commonImageList',
            primaryKey: 'src',
            list: [
              {
                src: `${preFix}${data.url}`,
                title: data.copyright
              }
            ]
          }
        })
        count += res2.result.data.addCount
      }catch (e) {
        stop = true
      }
    } else {
      stop = true
    }
    if(idx >=10) {
      stop = true
    }
  }
  return count
}
// 云函数入口函数
exports.main = async (event, context) => {
  let count = await getImg()
  return {count}
}

```javascript
// fetch.js
// 这里使用了axios库, 统一的异步请求发送处理
const axios = require('axios')

// 创建axios实例
const fetch = axios.create({
  timeout: 60000 // 请求超时时间
})

// request拦截器
fetch.interceptors.request.use(config => {
  return config
})

// 响应拦截器
fetch.interceptors.response.use(
  response => {
    // 抛出接口数据
    return response.data
  },
  error => {
    return Promise.reject(error)
  }
)

module.exports = fetch;
// 云函数的配置文件config.json
{
  "triggers": [
    {
      "name": "myTrigger",
      "type": "timer",
      // 这里是每天的23.00执行
      "config": "0 0 23 * * * *"
    }
  ]
}

// package.json
{
  "name": "interval",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "wx-server-sdk": "~2.1.2",
    "axios": "^0.19.2"
  }
}


以上是4个文件是目录位置如下图
项目目录


下面是小程序图片展现页面

<!--new.vue-->
<template>
	<view class="index">
		<block v-for="(item, index) in dataList" :key="item.src">
			<view class="card" @click="goDetail(item,index)">
				<image class="card-img" :src="item.src" mode="aspectFill"></image>
				<!--<text class="card-num-view">{{item.img_num}}P</text>-->
				<view class="card-bottm row">
					<view class="car-title-view row">
						<text class="card-title">{{item.title}}</text>
					</view>
					<view @click.stop="share(item)" class="card-share-view"></view>
				</view>
			</view>
		</block>
		<text class="loadMore">{{loadMoreText}}</text>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				refreshing: false,
				loadMoreText: '加载中...',
				dataList: [],
				totalCount: 0,
				fetchPageNum: 0,
				fetchPageSize: 5
			}
		},
		onLoad() {
			this.getData();
			uni.getProvider({
				service: 'share',
				success: (e) => {
					let data = []
					for (let i = 0; i < e.provider.length; i++) {
						switch (e.provider[i]) {
							case 'weixin':
								data.push({
									name: '分享到微信好友',
									id: 'weixin'
								})
								data.push({
									name: '分享到微信朋友圈',
									id: 'weixin',
									type: 'WXSenceTimeline'
								})
								break;
							case 'qq':
								data.push({
									name: '分享到QQ',
									id: 'qq'
								})
								break;
							default:
								break;
						}
					}
					this.providerList = data;
				},
				fail: (e) => {
					console.log('获取分享通道失败', e);
				}
			});
		},
		onReachBottom() {
			console.log('滑动到页面底部')
			if ((this.fetchPageNum) *this.fetchPageSize >= this.totalCount || this.dataList.length >= this.totalCount) {
				this.loadMoreText = '没有更多了'
				return;
			}
			this.getData();
		},
		onPullDownRefresh() {
			console.log('下拉刷新');
			this.refreshing = true;
			this.fetchPageNum = 0;
			this.getData();
		},
		methods: {
			async getData() {
				this.loadMoreText = '加载中...'
				const db = wx.cloud.database()
				let ret = await wx.cloud.callFunction({
						name: 'getDbListData',
						data: {
							dbName: 'commonImageList',
							pageNo: this.fetchPageNum + 1,
							pageSize: this.fetchPageSize,
							limitType: 3,
							params: {
							},
						}
					})
				// errMsg: "collection.get:ok"
				if (ret.errMsg !== 'cloud.callFunction:ok') {
					console.log('请求失败', ret)
					return;
				}
				this.totalCount = ret.result.totalCount
				const data = ret.result.data;
				if (this.refreshing && data[0] && data[0]._id === this.dataList[0]._id) {
					uni.showToast({
						title: '已经最新',
						icon: 'none',
					});
					this.refreshing = false;
					uni.stopPullDownRefresh();
					return;
				}

				let list = [];
				for (var i = 0; i < data.length; i++) {
					var item = data[i];
					list.push({
						fileID: item.fileID,
						img_num: 1,
						_id: item._id,
						title: item.nickName || item.title,
						src: item.fileID || item.src
					});
				}

				if (this.refreshing) {
					this.refreshing = false;
					uni.stopPullDownRefresh();
					this.dataList = list;
				} else {
					this.dataList = this.dataList.concat(list);
					this.fetchPageNum += 1;
				}
				if(data.length < this.fetchPageSize) {
					this.loadMoreText = '没有更多了'
				}
				if(this.dataList && this.dataList.length<=0) {
					this.loadMoreText = '暂无数据'
					this.refreshing = false;
					uni.stopPullDownRefresh();
					this.dataList = list;

				}
			},
			goDetail(e,index) {
				uni.navigateTo({
					url: `/pages/detail/detail?list=${encodeURIComponent(JSON.stringify(this.dataList))}&index=${index}`
				});
			},
			share(e) {
				if (this.providerList.length === 0) {
					uni.showModal({
						title: '当前环境无分享渠道!',
						showCancel: false
					})
					return;
				}
				let itemList = this.providerList.map(function(value) {
					return value.name
				})
				uni.showActionSheet({
					itemList: itemList,
					success: (res) => {
						uni.share({
							provider: this.providerList[res.tapIndex].id,
							scene: this.providerList[res.tapIndex].type && this.providerList[res.tapIndex].type === 'WXSenceTimeline' ?
								'WXSenceTimeline' : 'WXSceneSession',
							type: 0,
							title: 'uni-app模版',
							summary: e.title,
							imageUrl: e.img_src,
							href: 'https://uniapp.dcloud.io',
							success: (res) => {
								console.log('success:' + JSON.stringify(res));
							},
							fail: (e) => {
								uni.showModal({
									content: e.errMsg,
									showCancel: false
								})
							}
						});
					}
				})
			}
		}
	}
</script>

<style>

</style>


4.来吧;展示。

小程序现已发布,有兴趣可以体验一下;目前爬取图片数量有限。后面会越来多
在这里插入图片描述

5.PS

做这个小程序的初衷是为了了解一下uni-app打包成微信小程序,然后熟悉一下微信小程序的云开发功能;期间还是踩到了不少坑;这里不一一说明;有兴趣同学可以试着搞一下,遇到问题可以互相交流学习。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值