网站用户行为分析项目之会话切割(一)

news/2024/5/20 1:33:00/文章来源:https://shaonaiyi.blog.csdn.net/article/details/100731132

文章目录

  • 0x00 教程内容
  • 0x01 项目分析
          • 1. 项目背景
          • 2. 学习收获
          • 3. 数据源介绍
          • 4. 项目总体流程
          • 5. 最终数据结构
  • 0x02 编程实现
          • 1. 构建Maven项目
          • 2. 编码前准备工作
          • 3. 实现源数据的获取
          • 4. 解析日志源数据
          • 5. 日志清洗操作
  • 0x03 思路回顾
  • 0xFF 总结

0x00 教程内容

  1. 项目分析
  2. 编程实现

基础知识及环境准备:
1、Maven的构建,学会Scala编程
2、IDEA已经安装好了Scala插件

0x01 项目分析

1. 项目背景

我们在浏览网站的时候,我们的很多信息都会被网站的后台采集到,采集的方式有很多种,至于怎么采集,以后有机会再写教程详细说,这篇教程主要是讲解采集到了数据后,对数据进行一个切割的过程。关于信息的收集,可参考文章,自行了解一下:网站分析数据(即用户行为数据)的三种收集方式详解 如果有时间,再整理相应的实操教程出来。

会话切割:用户行为分析的前置工作,相当于一个前置处理过程而已。

2. 学习收获

学完此教程,可以学到平时工作上怎么实现会话切割的一整套流程?理解切割前后的数据是怎样的?更加熟悉Scala API的使用以及其他开发上的技巧等等。

3. 数据源介绍

目前我们已经采集到了三份数据:网站用户点击日志、用户Cookie的标签、网站域名的标签

一、网站用户点击日志(存储在HDFS),格式如下:
在这里插入图片描述

#type|server time|cookie|ip|url
pageview|2017-09-04 12:00:00|cookie1|127.0.0.3|https://www.baidu.com
click|2017-09-04 12:00:02|cookie1|127.0.0.3|https://www.baidu.com
pageview|2017-09-04 12:00:01|cookie2|127.0.0.4|https://www.baidu.com
click|2017-09-04 12:00:04|cookie1|127.0.0.3|https://www.baidu.com
pageview|2017-09-04 12:00:02|cookie2|127.0.0.4|http://news.baidu.com
click|2017-09-04 12:00:03|cookie2|127.0.0.4|http://news.baidu.com
pageview|2017-09-04 12:00:04|cookie2|127.0.0.4|http://music.baidu.com/?fr=tieba
pageview|2017-09-04 12:45:01|cookie1|127.0.0.3|https://tieba.baidu.com/index.html
click|2017-09-04 12:45:02|cookie1|127.0.0.3|https://tieba.baidu.com/index.html
click|2017-09-04 12:45:03|cookie1|127.0.0.3|https://tieba.baidu.com/index.html
hhhh|2017-09-04 12:45:03|cookie1|127.0.0.3|https://tieba.baidu.com/index.html
3333ss|2017-09-04 12:45:03|cookie1|127.0.0.3|https://tieba.baidu.com/index.html

解释
此可以通过网站的后台采集到,我们去访问了一次网页时,这是一个行为,我们叫这个行为称为pageview行为;我们点击(click)了网页的某个按钮,也会有一个点击行为;还有在网页中滚动、选定文字等等也是相应的行为……每个行为都会产生相应的信息,至于是什么信息,可以看一下上面的数据里面有什么内容,这些信息都可以被采集到后台。这里为了方便起见,只拿pageview与click这两个行为作为例子,这些行为与Session机制是分不开的。这里的数据的第一行是对应的列含义,除了第一行,其他行的列是以“|”分开。因为这些行为信息会很多,所以我们将其存储到HDFS上。

Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在Session对象中。有关使用Session 对象的详细信息,请参阅“ASP应用程序”部分的“管理会话”。注意会话状态仅在支持cookie的浏览器中保留。
——来自百度百科

通俗易懂描述:
至于会话,学过浏览器相关知识的人应该都比较清楚什么是会话,会话即session,我们在浏览网站的时候,会对网站发起一次会话,就好像我们用XShell建立一个会话窗口访问我们的服务器一样,那也是一个会话,而且你会发现,如果窗口很久不动它,它会自动断开连接。在我们浏览网站的时候也一样,我们的会话有效时长默认是30min,30min不动,默认断开会话。
这里我们所做的会话切割业务,就是根据我们网站后台记录的时间,每隔30分钟切割成一个会话。
我们现在已经有一个比较粗略概念,即会话有点类似与一种请求,而这个请求,Web服务器可以自动给你创建一个Session对象,里面可以存各种属性,包括pageview、click等等。

二、用户Cookie的标签(存储在HDFS),格式如下:
在这里插入图片描述

cookie1|固执
cookie2|有偏见
cookie3|执着
cookie4|执行力很强

解释
每个cookie都打上了对应的类型,作为标签。此过程可以由数据团队,根据机器学习的算法来实现,这里不纠结先,后期有时间会给出教程。因为这些行为信息也会很多,所以我们也将其存储到HDFS上。

Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。
——来自百度百科

三、网站域名的标签(存储在配置库,如数据库)

"www.baidu.com" -> "level1",
"www.taobao.com" -> "level2", 
"jd.com" -> "level3", 
"youku.com" -> "level4"

解释
我们自定义的给网站分的级别,已经打上了相应的级别标签,当然,也可能有些域名没有分级。这些域名远远没有行为信息那么多,我们可以考虑存储在传统数据库里面。

4. 项目总体流程

在这里插入图片描述
其实上面就是一个ETL的过程,最终我们会得到两张表,分别是TrackerLog表与TrackerSession表,也都是存储在HDFS上的,我们这里用的存储方式是Parquet格式。TrackerLog对应我们的原始日志的表,TrackerSession为我们切割后的Session信息表。
我们可以大致用肉眼看一下上面的十行数据,每30min切成成一个会话,我们可以看出来,是有三个会话的,如果我们最后切割出来有三个会话,则表示我们实操结果是对的。
但在此过程中,我们主要是实现的是上图中间的会话切割、生成会话这里边的业务。

5. 最终数据结构

a. 确定表字段

TrackerLog表的字段(暂时可以先忽略里面的数据):
在这里插入图片描述
TrackerSession表字段(暂时可以先忽略里面的数据):
在这里插入图片描述
字段解释
session_id:唯一标识我们的会话
session_server_time:最早访问的那条session创建的时间
landing_url:对应第一个访问的URL,即同属于一个session的最早时间那个
domain:域名

数据解释
观察前面两个表格的数据,表一共有10条,表二的pageview_count与click_count字段的数据加起来正好也是10条的。

b. 定义Schema信息
既然我们是准备用Parquet格式进行存储,那么就要定义好我们的Schema,如:

{"namespace": "com.shaonaiyi.spark.session","type": "record","name": "TrackerLog","fields": [{"name": "log_type", "type": "string"},{"name": "log_server_time", "type": "string"},{"name": "cookie", "type": "string"},{"name": "ip", "type": "string"},{"name": "url", "type": "string"}]
}
{"namespace": "com.shaonaiyi.spark.session","type": "record","name": "TrackerSession","fields": [{"name": "session_id", "type": "string"},{"name": "session_server_time", "type": "string"},{"name": "cookie", "type": "string"},{"name": "cookie_label", "type": "string"},{"name": "ip", "type": "string"},{"name": "landing_url", "type": "string"},{"name": "pageview_count", "type": "int"},{"name": "click_count", "type": "int"},{"name": "domain", "type": "string"},{"name": "domain_label", "type": "string"}]
}

将上面的Schema信息保存成两个文件,分别是:TrackerLog.avscTrackerSession.avsc,现在我们的准备工作已经完成了,接下来我们就可以开始构建一个项目了。

0x02 编程实现

1. 构建Maven项目

本人博客里面有很多教程,这里不再重复,相信学到这里的人,已经对这些基础知识相当熟练。
需要注意的是:
1、包名要与前面Schema信息定义的一致,如我的是:com.shaonaiyi.spark.session,当然,你可以继续先操作,不创建包名先。
在这里插入图片描述

2. 编码前准备工作

a. 引入依赖及插件(完整pom.xml文件如下)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.shaonaiyi</groupId><artifactId>spark-sessioncut</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.apache.spark</groupId><artifactId>spark-core_2.11</artifactId><version>2.2.0</version><!--<scope>provided</scope>--></dependency><dependency><groupId>org.apache.parquet</groupId><artifactId>parquet-avro</artifactId><version>1.8.1</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>1.8</source><target>1.8</target><testExcludes><testExclude>/src/test/**</testExclude></testExcludes><encoding>utf-8</encoding></configuration></plugin><plugin><groupId>net.alchim31.maven</groupId><artifactId>scala-maven-plugin</artifactId><version>3.1.6</version><executions><execution><goals><goal>compile</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.avro</groupId><artifactId>avro-maven-plugin</artifactId><version>1.7.7</version><executions><execution><phase>generate-sources</phase><goals><goal>schema</goal></goals><configuration><sourceDirectory>${project.basedir}/src/main/avro</sourceDirectory><outputDirectory>${project.basedir}/src/main/java</outputDirectory></configuration></execution></executions></plugin><plugin><artifactId>maven-assembly-plugin</artifactId><configuration><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs></configuration><executions><execution><id>make-assembly</id> <!-- this is used for inheritance merges --><phase>package</phase> <!-- 指定在打包节点执行jar包合并操作 --><goals><goal>single</goal></goals></execution></executions></plugin></plugins></build></project>

b. 引入Avro Schema文件
TrackerLog.avscTrackerSession.avsc两个文件上传到项目的avro文件夹(自己新创建)

c. 引入数据源文件并引入Scala SDK
将数据源文件(visit_log.txtcookie_label.txt)复制到项目的data文件夹(自己新创建),因为在开发的时候,我们一般是先将一部分测试的数据上传到项目来测试,测试完成后,再将路径修改为HDFS上的路径即可,这是开发的流程。创建scala代码源文件夹并引入Scala SDK,下面是目前的项目结构,请参考:
在这里插入图片描述

3. 实现源数据的获取

a. 根据Schema文件生成Java对应的类(因为Maven里引入了avro-maven-plugin插件,所以直接点击Maven里的compile即可生成相应的类)
在这里插入图片描述
编译完后,可以看到已经生成了相对应的文件,而且自动创建了包:
在这里插入图片描述
b. 新建一个工具类RawLogParserUtil

package com.shaonaiyi.sessionimport com.shaonaiyi.spark.session.TrackerLog/*** @Auther: shaonaiyi@163.com* @Date: 2019/9/12 09:40* @Description: 将每一行原始日志解析成TrackerLog对象*/
object RawLogParserUtil {def parse(line: String): Option[TrackerLog] = {if (line.startsWith("#")) Noneelse {val fields = line.split("\\|")val trackerLog = new TrackerLog()trackerLog.setLogType(fields(0))trackerLog.setLogServerTime(fields(1))trackerLog.setCookie(fields(2))trackerLog.setIp(fields(3))trackerLog.setUrl(fields(4))Some(trackerLog)}}
}

c. 新建一个项目入口类SessionCutETL

package com.shaonaiyi.sessionimport org.apache.spark.{SparkConf, SparkContext}/*** @Auther: shaonaiyi@163.com* @Date: 2019/9/12 10:09* @Description: 会话切割的程序主入口*/
object SessionCutETL {def main(args: Array[String]): Unit = {var conf = new SparkConf()conf.setAppName("SessionCutETL")conf.setMaster("local")var sc = new SparkContext(conf)val rawRDD: RDD[String] = sc.textFile("data/rawdata/visit_log.txt")rawRDD.collect().foreach(println)sc.stop()}}

执行后,可以看到已经加载到了原始日志的数据:
在这里插入图片描述
PS:因为没有配置Hadoop,所以前面会报此错误,可以忽略:
在这里插入图片描述

4. 解析日志源数据

a. 继续在SessionCutETL中添加解析日志源数据代码

val parsedLogRDD: RDD[Option[TrackerLog]] = rawRDD.map( line => RawLogParserUtil.parse(line))
parsedLogRDD.collect().foreach(println)

现在去执行的话会报错:
在这里插入图片描述
因为Driver与executor通讯的时候需要进行序列号,而Avro插件给我们生成的类中并没有给我们进行序列化,所以还需要给相应的类进行序列号,序列号很简单,只需要在类的后面实现序列化接口 Serializable 即可。
b. 实现TrackerLog类的序列化:
在这里插入图片描述
c. 重新执行就可以看到结果了,到此已经实现了我们的日志的解析:
在这里插入图片描述
d. 使用flatmap API调整输出格式
查看上面的代码:
val parsedLogRDD: RDD[Option[TrackerLog]] = rawRDD.map( line => RawLogParserUtil.parse(line))
我们返回的类型是RDD[Option[TrackerLog]],对于返回结果,我们的格式是None、Some(),这种类型,不是我们想要的结果,我们的结果应该更加简洁。所以可以修改此行代码为:
val parsedLogRDD: RDD[TrackerLog] = rawRDD.flatMap( line => RawLogParserUtil.parse(line))
运算结果如下:
在这里插入图片描述
此处需要清楚map与flatMap的区别,简而言之:map是一对一的关系,一行就是一个具体的类,所以多少行就有多少个类,然后每个类都切,切了后,这些类还存在;而flatMap则会对所有的行打平成一个类,然后进行切,最后是只有一个类。

5. 日志清洗操作

a. 非法类型的日志说明

仔细关系我们前面的日志,可以看到我们最后有两条数据的类型是hhhh和3333ss,显然不是合法的日志,这里我们需要将其过滤掉,在实际的日志里面脏数据可能各种各样,但处理流程都类似。

hhhh|2017-09-04 12:45:03|cookie1|127.0.0.3|https://tieba.baidu.com/index.html
3333ss|2017-09-04 12:45:03|cookie1|127.0.0.3|https://tieba.baidu.com/index.html

b. 定义合法类型(与main方法同级)
private val logTypeSet = Set("pageview", "click")
在这里插入图片描述
c. 修改解析代码,加上过滤条件
val parsedLogRDD: RDD[TrackerLog] = rawRDD.flatMap(RawLogParserUtil.parse(_)) .filter(trackerLog => logTypeSet.contains(trackerLog.getLogType.toString))

d. 重新执行,会发现后面的那两条脏数据已经没有显示出来了
在这里插入图片描述

0x03 思路回顾

1、首先,我们需要清楚,我们的大项目其实是网站用户行为分析,而会话切割只是项目里面的小环节,至于网站用户行为分析可以达到什么结果。我们这里边可以简单列举几个,比如说,我们可以通过分析一个人在浏览网站时点击的内容、打开的内容、停留的时间等等,初步判断此人是否对此内容特别感兴趣,得出这个结论之后,我们就可以对此人做定制化的推荐等等,当然这只是一个小小的例子。刚刚我们是从项目开发流程出发,而实际上,我们应该是已经知道我们可以获取到什么信息什么数据,然后,由我们的信息和数据,挖掘我们想要的功能。比如说,你现在有一个产品,需要找到你的商城网站里面、或者其他网站里面某些人对你同类型的产品特别感兴趣,你只需要筛选出这些人,那么我们就可以给这些人推荐你的产品,这些匹配度度高的人就是你的高级客户,你推销产品肯定也会更加顺利。所以呢,我们就要努力朝着这个方向去实现我们的目标,我们目标就是要筛选出这些与你产品匹配度极高的人
2、所以在此过程中,我们可以根据各种途径,拿到你需要的数据,当然,这些数据也可能是之前已经存在了的,也可能是你确定了目标之后才确定你是否想要的,缺什么数据就想方法去获取,然后整理一下存放到该存放的地方,像这些网页行为,数据量肯定是很大的,点击、打开、滑动等等都是一条数据,每个人都可以产生很多很多条,对于这些量大的数据,我们就可以存储到HDFS上,关于量少的,就可以存到其他地方,不固定,灵活进行存储选型。
3、这里教程没有提供收集数据的教程,如果有浏览过本博客的读者应该会清楚,我们的数据是怎么得到的,比如说Flume就可以实现,还有很多种方式。我们这里已经省略了那些过程,分析完成之后我们就可以进行编码去实现了,因为存储的数据都只是文本文件,而我们要做的,肯定是要先进行数据清洗,把不合法的数据过滤掉,那么根据什么条件进行过滤呢? 在学习传统数据库的时候,如MySQL,可以用where来确定过滤的条件,比如检索出年龄大于18岁的学生,那么年龄就是一个很关键的因素,而我们的文本文件中,其实是还没有真正去规定好字段的,只是在第一行确定了Schema信息而已,如果不进行字段的切分,那么每一行都要自定义一次,这样显然很麻烦。那么我们就可以统一将文本文件切分成一段一段的,什么字段对应什么意思、对应什么字段。每个字段都属于一行竖行,很显然,我们可以通过构建一个对象来对应上,一个类相当于一行数据,然后一行里面的每个字段,相当于一个对象里面的属性。类->行,属性->字段,所以我们需要在前面定义一个类。
4、我们的Spark作业在进行数据传输的时候,要先进行序列化,所以还要给我们的类进行序列化,Java里面的序列化类是Serializable,搞定之后就可以去获取我们的数据源了,然后清洗、过滤等,过程比较繁多,后期教程会继续完成。

0xFF 总结

  1. 其实Spark里面有内置的Kryo序列化接口,性能更好,而且更适合我们当前的应用场景,这个优化点留到项目后期再进行升级。
  2. 我们在测试的时候,看到很多启动时的提示信息,很影响我们查看,我们可以通过设置将其屏蔽掉,以方便我们开发,也一样在后期教程再写上。
  3. 俗话说得好:“台上一分钟,台下十年功。” 可是写教程不一样,操作半个钟,思路半天,写教程一天。这就是台下半个钟,台上十年功啊!感谢各位读者支持,感谢老汤,关注,评论,加油。
  4. 网站用户行为分析项目系列:
    网站用户行为分析项目之会话切割(一)
    网站用户行为分析项目之会话切割(二)
    网站用户行为分析项目之会话切割(三)

作者简介:邵奈一
全栈工程师、市场洞察者、专栏编辑
| 公众号 | 微信 | 微博 | CSDN | 简书 |

福利:
邵奈一的技术博客导航
邵奈一 原创不易,如转载请标明出处。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_733684.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网站正在建设中_兰州网站建设中常见的布局种类有什么

网站是由网页构成&#xff0c;这点许多从事网站建设或者是接触过网站开发的应该都比较清楚&#xff0c;目前虽然许多的企业都想要建设网站&#xff0c;但是对于网站的布局了解并不清楚&#xff0c;下面随小编一起来了解一下兰州网站建设中几种常见的布局吧。1、区块型为了网站优…

做服务端用Java还是PHP_建站用php还是java

建站用php还是java&#xff1f;建站用php&#xff0c;因为php是常用的网站编程语言&#xff0c;有全球超过81.7%的公共网站在服务器端采用PHP。而Java是一门面向对象编程语言&#xff0c;更适于系统程序的开发。phpPHP即“超文本预处理器”&#xff0c;是一种通用开源脚本语言。…

百度爬虫爬到虚拟链接 网站被黑_什么是爬虫?如何提高爬虫爬取网页速度?...

什么是爬虫&#xff1f;网络爬虫也叫网络机器人和网络蜘蛛&#xff0c;它可以代替人工按照一定的规则自动地的在互联网中进行数据采集与整理。各大搜索引擎也都有各自的名字&#xff0c;如百度蜘蛛&#xff1a;BaiduSpider&#xff0c;谷歌蜘蛛&#xff1a;Googlebot&#xff0…

jmeter怎么监控网站服务器,Jmeter监控服务器资源

1. 前言之前用Jmeter做性能测试时总是通过其他工具来监控服务器资源&#xff0c;通过查找资料&#xff0c;发现Jmeter自带的监控工具能监控tomcat&#xff0c;这种情况只能监控Tomcat支持的资源使用部分&#xff0c;完全是不够用的&#xff0c;于是发现有第三方插件支持Jmeter监…

91pay.php,电商网站使用支付宝转账付款功能代替支付宝支付接口

现在支付宝商户对于商家接入支付宝即时到账接口管理比较严格&#xff0c;一般都是需要支付宝企业账户才能申请开通即时到账接口的。这对于大部分个人商家来说&#xff0c;无疑不利于快速回笼资金。本接口通过一个变通的方式&#xff0c;利用支付宝系统中的转账付款功能&#xf…

建站难?史上最全指南 — 教你使用WordPress搭建出属于自己的站点!

文章目录引言购买服务器购买域名解析域名部署WordPress安装nginx服务器安装PHP运行环境新建个人站点下载并安装WordPress安装主题网站备案SSL证书&#xff08;HTTPS&#xff09;页面伪静态网站类型选择结语引言 很多朋友都想拥有自己的个人网站&#xff0c;但事实如果自己从头搭…

网站中文乱码?三招解决

发布网站后&#xff0c;不少小伙伴都会碰到中文乱码问题。 碰到这种问题不用慌&#xff0c;三招就可以解决&#xff1a; 第一招&#xff1a;设置好页面的编码&#xff0c;建议用utf-8编码格式&#xff0c;一招鲜&#xff0c;吃天下。 <meta http-equiv"Content-Type&qu…

网站开发知识结构

网站开发知识结构 https://github.com/TeamStuQ/skill-map https://blog.csdn.net/fenglailea/article/details/52609188 转载于:https://www.cnblogs.com/iamspecialone/p/11203256.html

ctfhub——网站源码python脚本解法

1.打开题目页面如下&#xff1a; 2.编写脚本之前&#xff0c;先学习一下python request模块中正常访问页面代码怎么写 import requests url "http://42.192.212.170/" r requests.get(url) print (r,r.status_code,end" ") 输出结果&#xff1a; 3.下…

python爬虫——获取网站中的特定块元素内容(二)

一、实现的目标 目标&#xff1a;获取如图所示网站中块元素的内容 二、代码编写 import requests #导入request模块 import re #导入re模块 url "https://www.baidu.com/" #等会要爬的url地址 header {User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:9…

python爬虫——获取网站中的特定块元素内容(一)

一、实现的目标 目标&#xff1a;获取如图所示网站中所标的元素内容 二、代码编写 import requests import re import json url "https://open.weibo.com/" header {User-Agent:ozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0…

wordpress 搭建的博客: 增加网站备案信息

问题描述 使用阿里云的主机&#xff0c;搭建了一个基于wordpress的博客&#xff0c;因为注册的域名是.com&#xff0c;需要网站开启后&#xff0c;增加网站备案的信息搭建好 wordpress 博客后&#xff0c;发现没有地方配置【网站备案信息】 主题 我使用的是 wordpress 的一个…

图片优化_网站图片SEO优化应该怎么做

作为一名SEOer人员一定要学会图片SEO优化&#xff0c;现在百度对图片优化这块相当的看重&#xff0c;并且会抓取并收录图片&#xff0c;最直接的表现就是搜索某一个关键词点击【图片】的时候能看见一大堆的相关图片&#xff0c;由此可见搜索引擎对图片识别能力已经越来越强了&a…

效果图网站、外包平台接单平台有哪些?

作为一名设计师或画图员&#xff0c;设计方案、画图、收集素材、接单、学习充电等&#xff0c;都有哪些网站可以用到呢&#xff1f;下面我就整理了一下。 综合设计类网站 国外室内设计网站 https://www.houzz.com/ 国外优秀设计作品网站 https://www.behance.net/ 国外室内设计…

自定义表单提交筛选分页怎么做_如何优化网站的筛选页面?

网站设计的重要目标之一就是做好清晰的导航系统&#xff0c;这不论是对网站的信息结构、还是用户体验&#xff0c;都有着重要的影响。这也是网站SEO优化工作中需要考虑的重要因素之一。在导航系统当中&#xff0c;通过不同筛选条件组成不同网站页面的&#xff0c;就是分页导航&…

类似纪念碑谷的unity2d素材包_短视频文案怎么写吸引人?短视频文案素材网站有哪些?(纯干货)...

你会写短视频文案吗&#xff1f;有没有被那几十个字绞尽脑汁&#xff1f;你知道短视频文案怎么写吸引人吗&#xff1f;你是不是看了很多短视频文案怎么写吸引人的文章还是仍然不会写?.....你是不是也正在为这些问题愁眉不展&#xff1f;今天这篇文章就来说说短视频文案怎么写吸…

什么是seo(seo是什么意思?)

什么是seo(seo是什么意思?) SEO是就会实践才有发言权的&#xff0c;在不间断学习途中&#xff0c;敢于总括和创意&#xff0c;深信能让需要的seo推广取的非常好成效。如果您在学习了部分seo推广教程或者参加完相干培训学校以后&#xff0c;不能实践&#xff0c;只说不练&#…

seo网络培训机构(seo教育)

seo网络培训机构(seo教育) 再一个&#xff1a;常宁网络营销-小高seo是需要参加培训学习的&#xff0c;敢于掌握关键词优化分享对我们攀升百度排序排名绝对有益处,百度优化要按照网页如今的状态来定&#xff0c;按照状态应对&#xff0c;您能够实施百度优化和网站版面改动设计&a…

seo的优势与缺点(seo误区)

seo的优势与缺点(seo误区) 另一方面&#xff0c;真正的SEOer不只是为了追求收录、排名&#xff0c;快速的响应速度是提高用户体验度的基础&#xff0c;这对整个搜索引擎优化及营销都是非常有利的。&#xff0c;但随着搜索引擎的发展愈来愈全面&#xff0c;只针对搜索引擎喜好的…

seo的设置与优化(seo页面优化的方法)

seo的设置与优化(seo页面优化的方法) 为了满足SEO的意图和长期排名&#xff0c;建立SEO的营销策略围绕主题&#xff0c;而不是关键词。如果你这样做&#xff0c;在任何情况下&#xff0c;你会发现你可以自然地优化重要的关键字。了解你的目标受众(也被称为买家角色)以及他们感兴…