当前位置: 首页 > news >正文

导航网站制作长春网站建设 4435

导航网站制作,长春网站建设 4435,在招聘网站做销售怎么样,电脑网站建设方案目录 第一部分、前言 1、获取心知天气API接口 2、硬件准备 第二部分、电脑串口助手调试WIFI模块获取天气 1、ESP8266获取天气的流程 2、具体步骤 第三部分、STM32驱动ESP8266模块获取天气数据 1、天气数据的解析 1.1、什么函数来解析天气数据? 2.1、解析后…

目录

第一部分、前言

1、获取心知天气API接口

2、硬件准备

第二部分、电脑串口助手调试WIFI模块获取天气

1、ESP8266获取天气的流程

2、具体步骤

第三部分、STM32驱动ESP8266模块获取天气数据

1、天气数据的解析

1.1、什么函数来解析天气数据?

2.1、解析后的数据如何使用?

 2、相关代码

2.1、main.c文件

2.2、esp8266.c文件

第四部分、总结

1、效果展示

2、完整的工程

3、补充


第一部分、前言

        这篇博客拖了很久很久,本来是打算和前面一篇一起发出来的,但是那段时间因为一些事情耽搁了,这篇博客写了一半,剩下的一直都没有写,其次就是人也有点懒,也不太想动🤪🤪。

        这几天考试周来了,复习又不想复习,不如把这篇内容更新完整,这篇更新完之后,STM32专栏应该不会再更新了。

        然后,后面我打算出一期C语言的学习笔记专栏,再后面就是FPGA的学习笔记专栏。想是这么想的,不知道能不能做好,哈哈🤭。

1、获取心知天气API接口

        这里还是希望大家先去看我的第一篇博客:【STM32训练—WiFi模块】第一篇、STM32驱动ESP8266WiFi模块获取网络时间通过这篇博客你会明白WIFI模块获取网络流程是什么样子的,搞懂了这个,你会发现获取天气和获取时间的步骤完全一样,代码也没有什么大的变化。

        接着再来说一下心知天气,上一篇文章提到时间的接口是由苏宁后台提供的“quan.suning.com/getSysTime.do”,那么这里想获取天气,那么也需要一个API的接口,这里的API接口由心知天气给我们提供。

        因此需要注册一个心知天气,获取自己的密钥。关于注册的过程可以参考心知天气提供的文档:注册与登陆 | 心知天气文档 (seniverse.com)

        注册完成后,如何获取属于自己的API接口呢,参考文档如下:查看/修改你的API密钥 (yuque.com)

        这是我的API接口,点进去之后就会看到目前杭州的天气数据:https://api.seniverse.com/v3/weather/now.json?key=SwLQ3i0Q5TNa6NSKT&location=hangzhou&language=zh-Hans&unit=c

        点击上面的链接,就会获取到天气数据,接下来的步骤就和前面获取时间一样,主要区别就是将时间的API接口换成刚刚注册得到的心知天气的API接口即可是不是发现原来也就这么回事。

2、硬件准备

         STM32选用核心板F103C8T6,然后再加一个ESP8266 WiFi模块(任何型号应该都可以,我这次用的ESP-01s),最后需要一个USB-TTL模块用来打印串口数据。

        需要注意的是:我的这个ESP-01S,有一个EN使能端,必须要给高电平才能用,上一篇博客用的那个WIFI模块没有EN使能端。所以希望大家注意自己的模块。

第二部分、电脑串口助手调试WIFI模块获取天气

1、ESP8266获取天气的流程

        流程和获取时间的流程大致一样,只不过这里获取的为天气数据。

2、具体步骤

 第一步、AT指令集

0:AT
1:AT+RST
2:AT+CWMODE=1
3:AT+CIPMUX=0
4:AT+CWJAP="你的WiFi名称","你的WiFi密码"
5:AT+CIPMODE=1
6:AT+CIPSTART="TCP","api.seniverse.com",80
7:AT+CIPSEND
8:GET https://api.seniverse.com/v3/weather/now.json?key=SwLQ3i0Q5TNa6NSKT&location=hangzhou&language=en&unit=c
9:+++

        注意:所有串口步骤同前一篇文章,这里直接有区别的步骤为第八步,因此这里直接跳转到第八步

 第八步、连接目标的服务器,TCP是传输协议,api.seniverse.com是心知天气服务器的IP地址,80是服务器端口。

 第十步、第九步和前文一样,接着再发送获取数据的请求,得到天气数据

 第十一步、关于退出透传的方式也和前面博客完全一样,这里就不再展示,所以一定要看第一篇文章,那个文章介绍的太详细了。

第三部分、STM32驱动ESP8266模块获取天气数据

1、天气数据的解析

        这里天气的解析我调用了cJSON的库,你不用管这个库怎么写的,原理是啥,知道它是怎么用的就可以了,例如调用什么函数来解析天气数据?解析后的数据如何使用?弄明白这两个问题,就够了。

        1.1、什么函数来解析天气数据?

        时间太久了,我都不知道我哪里弄来的这个函数,反正挺好用的,侵权联系我删除!

        这个函数我放在我工程的"cJSON.c"文件最下面。

/*********************************************************************************
* Function Name    : cJSON_WeatherParse,解析天气数据
* Parameter		   : JSON:天气数据包  results:保存解析后得到的有用的数据
* Return Value     : 0:成功 其他:错误
* Function Explain : 
* Create Date      : 2017.12.6 by lzn
**********************************************************************************/
int cJSON_WeatherParse(char *JSON, Results *results)
{cJSON *json,*arrayItem,*object,*subobject,*item;json = cJSON_Parse(JSON); //解析JSON数据包if(json == NULL)		  //检测JSON数据包是否存在语法上的错误,返回NULL表示数据包无效{printf("Error before: [%s] \r\n",cJSON_GetErrorPtr()); //打印数据包语法错误的位置return 1;}else{if((arrayItem = cJSON_GetObjectItem(json,"results")) != NULL); //匹配字符串"results",获取数组内容{int size = cJSON_GetArraySize(arrayItem);     //获取数组中对象个数printf("cJSON_GetArraySize: size=%d \r\n",size); if((object = cJSON_GetArrayItem(arrayItem,0)) != NULL)//获取父对象内容{/* 匹配子对象1 */if((subobject = cJSON_GetObjectItem(object,"location")) != NULL){printf("---------------------------------subobject1-------------------------------\r\n");if((item = cJSON_GetObjectItem(subobject,"id")) != NULL)   //匹配子对象1成员"id"{printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);memcpy(results[0].location.id,item->valuestring,strlen(item->valuestring));}if((item = cJSON_GetObjectItem(subobject,"name")) != NULL) //匹配子对象1成员"name"{printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);memcpy(results[0].location.name,item->valuestring,strlen(item->valuestring));}if((item = cJSON_GetObjectItem(subobject,"country")) != NULL)//匹配子对象1成员"country"{printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);memcpy(results[0].location.country,item->valuestring,strlen(item->valuestring));}if((item = cJSON_GetObjectItem(subobject,"path")) != NULL)  //匹配子对象1成员"path"{printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);memcpy(results[0].location.path,item->valuestring,strlen(item->valuestring));}if((item = cJSON_GetObjectItem(subobject,"timezone")) != NULL)//匹配子对象1成员"timezone"{printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);memcpy(results[0].location.timezone,item->valuestring,strlen(item->valuestring));}if((item = cJSON_GetObjectItem(subobject,"timezone_offset")) != NULL)//匹配子对象1成员"timezone_offset"{printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);memcpy(results[0].location.timezone_offset,item->valuestring,strlen(item->valuestring));}}/* 匹配子对象2 */if((subobject = cJSON_GetObjectItem(object,"now")) != NULL){printf("---------------------------------subobject2-------------------------------\r\n");if((item = cJSON_GetObjectItem(subobject,"text")) != NULL)//匹配子对象2成员"text"{printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);memcpy(results[0].now.text,item->valuestring,strlen(item->valuestring));}if((item = cJSON_GetObjectItem(subobject,"code")) != NULL)//匹配子对象2成员"code"{printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);memcpy(results[0].now.code,item->valuestring,strlen(item->valuestring));}if((item = cJSON_GetObjectItem(subobject,"temperature")) != NULL) //匹配子对象2成员"temperature"{printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);memcpy(results[0].now.temperature,item->valuestring,strlen(item->valuestring));}}/* 匹配子对象3 */if((subobject = cJSON_GetObjectItem(object,"last_update")) != NULL){printf("---------------------------------subobject3-------------------------------\r\n");printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",subobject->type,subobject->string,subobject->valuestring);memcpy(results[0].last_update,item->valuestring,strlen(subobject->valuestring));}} }}cJSON_Delete(json); //释放cJSON_Parse()分配出来的内存空间return 0;
}

        2.1、解析后的数据如何使用?

        调用上面那个函数后,解析的数据存放在一个双层结构体当中,因此只需访问结构体的成员就可以,每个成员的名称与心知天气返回的名称相匹配。

        具体的信息参考心知天气的文档:极速实况 (yuque.com)

 2、相关代码

        2.1、main.c文件

#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
#include "esp8266.h"
#include "cJSON.h" //解析天气//天气数据
extern unsigned char Weather_buff[300];
//天气解析
Results Weather_results[] = {{0}};int main()
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//中断控制器分组设置Usart1_Init(115200);Usart2_Init(115200);LED_Init();delay_init();//初始化很重要//用不了的函数一般都是没有初始化ESP8266_Init();Get_current_weather();//获取天气while(1){LED0 = 0;delay_ms(500);delay_ms(500);delay_ms(500);delay_ms(500);LED0 = 1;delay_ms(500);delay_ms(500);delay_ms(500);delay_ms(500);cJSON_WeatherParse((char *)Weather_buff, Weather_results);printf("%s",Weather_buff);	//打印结构体内内容printf("\r\n 打印结构体内内容如下: \r\n");printf("%s \r\n",Weather_results[0].now.text);printf("%s \r\n",Weather_results[0].now.temperature);printf("%s \r\n",Weather_results[0].location.path);printf("%s \r\n",Weather_results[0].location.country);}}

        2.2、esp8266.c文件

#include "stm32f10x.h"
#include "sys.h"
#include "string.h"
#include "stdlib.h"
#include "esp8266.h"#include "usart.h"
#include "delay.h"
#include "led.h"//WIFI和密码·
#define ESP8266_WIFI_INFO		"AT+CWJAP=\"iPhone111\",\"123456789\"\r\n"
//心知天气的API
#define Weather_TCP		"AT+CIPSTART=\"TCP\",\"api.seniverse.com\",80\r\n"
//心知天气GET报文
/*这里城市  恩施    语言为  英文*/
#define Weather_GET		"GET https://api.seniverse.com/v3/weather/now.json?key=SwLQ3i0Q5TNa6NSKT&location=enshi&language=en&unit=c\r\n"//ESP8266数据存放
unsigned char esp8266_buf[300] = {0};
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;
//存放天气数据
unsigned char Weather_buff[300];   //位数是随机确定的/**************************************************************************/
//函数作用:ESP8266_Init初始化函数
//函数名称:ESP8266_Init(void);
//内部参数:
//修改日期:2022年4月18日  下午16:18
//作者:    大屁桃
/**************************************************************************/
void ESP8266_Init(void)
{ESP8266_Clear();/*让WIFI推出透传模式*/while(ESP8266_SendCmd("+++", ""))  delay_ms(500);UsartPrintf(USART_DEBUG, "1.AT\r\n");while(ESP8266_SendCmd("AT\r\n", "OK"))delay_ms(500);////加一步ESP8266复位操作UsartPrintf(USART_DEBUG, "2.RST\r\n");ESP8266_SendCmd("AT+RST\r\n", "");delay_ms(500);ESP8266_SendCmd("AT+CIPCLOSE\r\n", "");delay_ms(500);/UsartPrintf(USART_DEBUG, "3.CWMODE\r\n");while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))delay_ms(500);UsartPrintf(USART_DEBUG, "4.AT+CIPMUX\r\n");while(ESP8266_SendCmd("AT+CIPMUX=0\r\n", "OK"))delay_ms(500);UsartPrintf(USART_DEBUG, "5.CWJAP\r\n");while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "WIFI GOT IP"))delay_ms(500);delay_ms(500);delay_ms(500);UsartPrintf(USART_DEBUG, "ESP8266_Init OK\r\n");
}/*获取网络天气数据*/
/**************************************************************************/
//函数作用:获取心知天气函数
//函数名称:Get_current_weather(void);
//内部参数:
//修改日期:2022年4月18日  下午16:18
//作者:    大屁桃
/**************************************************************************/
void Get_current_weather(void)
{ESP8266_Clear();UsartPrintf(USART_DEBUG, "6.Weather_TCP OK\r\n");	while(ESP8266_SendCmd(Weather_TCP, "CONNECT"))delay_ms(500);delay_ms(500);UsartPrintf(USART_DEBUG, "7.AT+CIPMODE=1 OK\r\n");		while(ESP8266_SendCmd("AT+CIPMODE=1\r\n", "OK"))delay_ms(500);delay_ms(500);delay_ms(500);
/*sizeof(Weather_GET),必须用sizeof函数,用strlen没有用*/  	ESP8266_SendData((u8 *)Weather_GET, sizeof(Weather_GET)); //发送AT+CIPSEND  以及 Weather_GETESP8266_GetIPD_GET(200,Weather_buff);ESP8266_Clear();//清除缓存数据	delay_ms(500);delay_ms(500);while(ESP8266_SendCmd("+++", ""))      /*退出透传模式*/delay_ms(500);UsartPrintf(USART_DEBUG, "+++ OK\r\n");	while(ESP8266_SendCmd("AT\r\n", "OK"))   //验证是否退出透传模式delay_ms(500);UsartPrintf(USART_DEBUG, "1.AT\r\n");
}/**************************************************************************/
//函数作用:串口二中断函数
//函数名称:USART2_IRQHandler();
//内部参数:
//修改日期:2022年4月18日  下午4:18
//作者:    大屁桃
/**************************************************************************/
void USART2_IRQHandler(void)
{if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断{if(esp8266_cnt >= sizeof(esp8266_buf))	esp8266_cnt = 0; //防止串口被刷爆				esp8266_buf[esp8266_cnt++] = USART2->DR;  //		USART_SendData(USART1,USART2->DR);      //让接收到的数据打印在串口一上USART_ClearFlag(USART2, USART_FLAG_RXNE);}
}//==========================================================
//	函数名称:	ESP8266_Clear
//
//	函数功能:	清空缓存
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP8266_Clear(void)
{memset(esp8266_buf, 0, sizeof(esp8266_buf));esp8266_cnt = 0;}
//==========================================================
//	函数名称:	ESP8266_WaitRecive
//
//	函数功能:	等待接收完成
//
//	入口参数:	无
//
//	返回参数:	REV_OK-接收完成		REV_WAIT-接收超时未完成
//
//	说明:		循环调用检测是否接收完成
//==========================================================
_Bool ESP8266_WaitRecive(void)
{if(esp8266_cnt == 0) 							//如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数return REV_WAIT;if(esp8266_cnt == esp8266_cntPre)				//如果上一次的值和这次相同,则说明接收完毕{esp8266_cnt = 0;							//清0接收计数return REV_OK;								//返回接收完成标志}esp8266_cntPre = esp8266_cnt;					//置为相同return REV_WAIT;								//返回接收未完成标志}//==========================================================
//	函数名称:	ESP8266_GetIPD
//
//	函数功能:	copy天气数据到Weather_buff数组里面
//
//	返回参数:	平台返回的原始数据
//
//	说明:		copy天气数据到Weather_buff
//==========================================================unsigned char *ESP8266_GetIPD_GET(unsigned short timeOut,u8 *buff)//这里我用了一个全局变量将esp8266buf储存到这个全局变量里面
{do{delay_ms(5);													} while(timeOut--);strcpy((char*)buff,(char*)esp8266_buf);return buff;														
}/*还未用到*/
//==========================================================
//	函数名称:	ESP8266_GetIPD
//
//	函数功能:	获取平台返回的数据
//
//	入口参数:	等待的时间(乘以10ms)
//
//	返回参数:	平台返回的原始数据
//
//	说明:		不同网络设备返回的格式不同,需要去调试
//				如ESP8266的返回格式为	"+IPD,x:yyy"	x代表数据长度,yyy是数据内容
//==========================================================
unsigned char *ESP8266_GetIPD(unsigned short timeOut)
{char *ptrIPD = NULL;do{if(ESP8266_WaitRecive() == REV_OK)								//如果接收完成{ptrIPD = strstr((char *)esp8266_buf, "IPD,");				//搜索“IPD”头if(ptrIPD == NULL)											//如果没找到,可能是IPD头的延迟,还是需要等待一会,但不会超过设定的时间{//UsartPrintf(USART_DEBUG, "\"IPD\" not found\r\n");}else{ptrIPD = strchr(ptrIPD, ':');							//找到':'if(ptrIPD != NULL){ptrIPD++;return (unsigned char *)(ptrIPD);}elsereturn NULL;}}delay_ms(5);													//延时等待} while(timeOut--);return NULL;														//超时还未找到,返回空指针}
//==========================================================
//	函数名称:	ESP8266_SendCmd
//
//	函数功能:	发送命令
//
//	入口参数:	cmd:命令
//				res:需要检查的返回指令
//
//	返回参数:	0-成功	1-失败
//
//	说明:		
//==========================================================
_Bool ESP8266_SendCmd(char *cmd, char *res)
{unsigned char timeOut = 250;Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));while(timeOut--){if(ESP8266_WaitRecive() == REV_OK)							//如果收到数据{		if(strstr((const char *)esp8266_buf, res) != NULL)		//如果检索到关键词{ESP8266_Clear();									//清空缓存return 0;}}delay_ms(10);}return 1;}//==========================================================
//	函数名称:	ESP8266_SendData
//
//	函数功能:	发送数据
//
//	入口参数:	data:数据
//				len:长度
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP8266_SendData(unsigned char *data, unsigned short len)
{char cmdBuf[32];ESP8266_Clear();								//清空接收缓存sprintf(cmdBuf, "AT+CIPSEND\r\n");		//发送命令if(!ESP8266_SendCmd(cmdBuf, ">"))				//收到‘>’时可以发送数据{UsartPrintf(USART_DEBUG, "8.AT+CIPSEND\r\n");/*发送请求数据*/Usart_SendString(USART2, data, len);		//发送设备连接请求数据		}
}

第四部分、总结

1、效果展示

        这是连接单片机后,单片机通过串口返回的数据,这里串口只展示了当前天气、当前温度,所在地区和所在国家的数据,若想增加在主程序中增加即可。

        单片机通过串口返回的数据和网址上显示的一致。

 2、完整的工程

        完整的工程代码点击该链接下载,无需积分,直接下载:STM32工程文件​​​​​​​

3、补充

        这篇博客说明了天气的获取方式,天气的读取,后面想做天气显示等应用,只需要加上LCD的驱动程序即可,花里胡哨的功能要靠自己去琢磨噻。

        最后希望博客对你有帮助,喜欢的话可以点个赞呢👍👍👍。


文章转载自:
http://totemite.tyjp.cn
http://six.tyjp.cn
http://emplane.tyjp.cn
http://cariocan.tyjp.cn
http://achromaticity.tyjp.cn
http://statehood.tyjp.cn
http://restorative.tyjp.cn
http://socius.tyjp.cn
http://abortionist.tyjp.cn
http://mucilaginous.tyjp.cn
http://bandstand.tyjp.cn
http://deserving.tyjp.cn
http://masterate.tyjp.cn
http://heartless.tyjp.cn
http://ewelease.tyjp.cn
http://pulicide.tyjp.cn
http://nucleonium.tyjp.cn
http://cyclophosphamide.tyjp.cn
http://parahydrogen.tyjp.cn
http://overcome.tyjp.cn
http://scorpii.tyjp.cn
http://unphilosophical.tyjp.cn
http://ewigkeit.tyjp.cn
http://prawn.tyjp.cn
http://diffusible.tyjp.cn
http://careerist.tyjp.cn
http://dipolar.tyjp.cn
http://peritrichate.tyjp.cn
http://ragbolt.tyjp.cn
http://atonement.tyjp.cn
http://formulism.tyjp.cn
http://ultraliberal.tyjp.cn
http://thersites.tyjp.cn
http://cumin.tyjp.cn
http://microbicide.tyjp.cn
http://unbuilt.tyjp.cn
http://betacam.tyjp.cn
http://judenhetze.tyjp.cn
http://russetish.tyjp.cn
http://transshipment.tyjp.cn
http://naker.tyjp.cn
http://diastem.tyjp.cn
http://handicraftsman.tyjp.cn
http://transformant.tyjp.cn
http://thixotropy.tyjp.cn
http://necrotize.tyjp.cn
http://raster.tyjp.cn
http://blacklist.tyjp.cn
http://anabiosis.tyjp.cn
http://atlantic.tyjp.cn
http://serific.tyjp.cn
http://discursiveness.tyjp.cn
http://euphorbiaceous.tyjp.cn
http://occur.tyjp.cn
http://faithfully.tyjp.cn
http://hypochondriacal.tyjp.cn
http://preexistent.tyjp.cn
http://hypaesthesia.tyjp.cn
http://hma.tyjp.cn
http://bicentric.tyjp.cn
http://scorching.tyjp.cn
http://exoterical.tyjp.cn
http://tutenague.tyjp.cn
http://kinchinjunga.tyjp.cn
http://anear.tyjp.cn
http://bedewed.tyjp.cn
http://darlene.tyjp.cn
http://reinhold.tyjp.cn
http://formidable.tyjp.cn
http://samar.tyjp.cn
http://hatless.tyjp.cn
http://lapidarian.tyjp.cn
http://neurofibrilar.tyjp.cn
http://frowzily.tyjp.cn
http://cosie.tyjp.cn
http://raggedly.tyjp.cn
http://gigantean.tyjp.cn
http://spifflicate.tyjp.cn
http://concertation.tyjp.cn
http://skeeter.tyjp.cn
http://immortalization.tyjp.cn
http://bail.tyjp.cn
http://innumerous.tyjp.cn
http://decasyllabic.tyjp.cn
http://semiblind.tyjp.cn
http://hindustan.tyjp.cn
http://bangladeshi.tyjp.cn
http://knur.tyjp.cn
http://timpanist.tyjp.cn
http://unpatriotic.tyjp.cn
http://marina.tyjp.cn
http://eez.tyjp.cn
http://orchidist.tyjp.cn
http://unprotestantize.tyjp.cn
http://international.tyjp.cn
http://trithing.tyjp.cn
http://pressboxer.tyjp.cn
http://anacrusis.tyjp.cn
http://quixotry.tyjp.cn
http://towage.tyjp.cn
http://www.dt0577.cn/news/93992.html

相关文章:

  • 成都十大广告公司排名宁波seo推广外包公司
  • python 新闻网站开发百度登录入口
  • wordpress quick chat湖南企业竞价优化
  • 淘宝刷网站建设seo零基础入门教程
  • 关于.net网站开发外文书籍关键词代做排名推广
  • 盘锦做网站价格企业查询系统
  • 谷歌有趣的网站百度手机网页版
  • 个人可以做招聘网站吗网络服务提供者收集和使用个人信息应当符合的条件有
  • 益阳seo快速排名乐山网站seo
  • wordpress分站中国最权威的网站排名
  • 西安便宜做网站百度模拟点击软件判刑了
  • php网站的数据库怎么做备份北京seo运营推广
  • 做网站可以做什么免费网站怎么注册
  • 关于销售网站建设的短文百度免费注册
  • 没有网站seo怎么做百度健康
  • 毕节网站建设企业网站快速排名
  • 公司做网站的网络营销有哪些形式
  • 网站建设怎么打开关键词工具软件
  • 网站如何做双语言热门推广平台
  • 河东苏州网站建设google ads
  • 网站主页图片尺寸可以推广的软件有哪些
  • 省心的专业建设网站公司百度竞价排名叫什么
  • 电子商务网站建设与管理学习心得广东疫情最新数据
  • 国内wordpress最好的主题seo顾问服务 乐云践新专家
  • 做网站哪个系统最好怎么做盲盒
  • 自己做pc网站建设北京seo软件
  • 网站首页被k 内页还有百度度小店申请入口
  • 广州招聘网网站开发seo推广策划
  • 单页网站怎么做外链seo点击排名软件营销工具
  • 常德网站建设制作论文收录网站排名