InterceptorCompontent-组件注入概念

前言

本来想定义为拦截器概念的…后来想想好像不对..应该是注入器概念..不过组件名都写好了 就懒得改了.

写这个小功能的原因很简单 目前开发方式都是所有的js放一个文件里了,那么如果我有多个页面,每个页面执行不同的函数 实现方式是不是很简单?

1
2
3
4
5
6
7
function indexCompontent(){
console.log('index')
}
if($('js-index').length>0){
indexCompontent();
}

记一次nginx反向代理内网wordpress

记一次nginx反向代理内网wordpress

参考

nginx反向代理wordpress

nginx反向代理wordpress.conf

Nginx proxy_set_header 理解

说明

公网ip为 233.233.233.233
代理服务器内网ip为 10.10.10.10
wordpress内网服务器ip为 10.0.0.1
其中nginx代理服务器可以访问内网.
需要绑定的域名为abc.com,
但是目前域名未备案 所以只能绑定公网ip也就是233.233.233.233

第一种解决方案

不更改wordpress的home_url和site_url 这两个url保持原来的域名不变 在nginx代理服务器那层利用sub_filter 把域名进行替换

第二种解决方案

更改wordpress的home_url和site_url为新域名.并且传递正确的Host.

这里采用的是第二种解决方案.第一种解决方案实际上可以看上述的参考

代理服务器层 conf配置

1
2
3
4
5
location /{
proxy_pass http://10.0.0.1:80;
proxy_set_header Host 233.233.233.233; # 这里必须要传递正确的公网ip 公网ip如果有端口的加上端口 比如 233.233.233.233:3030
proxy_set_header X-Real-IP $remote_addr;
}

这里值得注意的就是proxy_set_header Host 233.233.233.233;

这里的Host如果用 proxy_set_header Host $host:$proxy_port;

那么这个$host:$proxy_port;解析后会变成10.10.10.10:80;

然而在wordpress中 我们的home_url和site_url绑定的是233.233.233.233 所以 这里不能使用$host:$proxy_port;否则会造成绑定域名不匹配 从而导致一些问题出现.

具体请参考Nginx proxy_set_header 理解

nodejs微服务设计笔记

前言

豆瓣读书

这本书简单的介绍了如何使用nodejs来搭建微服务,一本实践与理论结合的书籍,如果对于微服务有比较深刻的了解就可以不用看这本书了,但是对于门外汉来说这本书还是有比较大的价值.

seneca

github

本书大半部分都围绕这个框架来写的. 这个框架就是实现微服务的一个工具罢了.
框架使用了匹配模式来触发函数,从而细粒化函数,比如.

1
2
3
4
5
6
7
seneca.add({role:"math",cmd:"sum"},function(msg,res){
var sum=msg.left+msg.right
res(null,sum)
})
seneca.act({role:"math",cmd:"sum",left:1,right:2},console.log)

add就是添加,act就是触发, 那么这个触发规则就是匹配模式了,越精确的就越优先匹配

1
2
3
4
5
{x:1,y:1}//func1
{x:1}//func2
act:{x:1,y:1}//触发func1
act:{x:1}//触发func2

这个也是这个框架的核心思想. 并且利用这个框架还可以使用plugin的方式

1
2
3
4
5
6
7
8
function math(ops){
this.add({role:"math",cmd:"sum"},function(msg,res){
var sum=msg.left+msg.right:
res(null,sum)
})
}
require('seneca')().use(math).act({role:'math',cmd:'sum',left:1,right:2})

通过插件那么可以细粒化各种业务逻辑,封装成一个个函数.

另一个seneca结合express也可以快速生成restfulApi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//省略一些add代码
seneca.add({role:"math",cmd:"sum"},function(arg,res){
var sum=10;
var result=sum+arg.id;
res(null,result);
})
seneca.add({role:"math",cmd:"print"},function(arg,res){
res(null,arg.printId)
})
seneca.act('role:web',{
use:{
prefix:"/api", //url前缀
pin:{
role:"math", //需要绑定哪个role分组
action:"*",//设置为*的意思是可以触发role分组下的所有的cmd
},
map:{
sum:{
GET:true,
suffix:"/:id" //通过arg.id获取 同等也可以/:id/:xx/:xx
},
print:{
GET:true,
POST:true,
suffix:"/:id"
}
}
}
})
app.use(seneca.export('web'));//app为express实例

。。。果然技术更新都是飞快..上述的express绑定已经不适用于现在的seneca了.
使用上述代码会报错app.use() requires middleware functions

新版的绑定请参考官网start

anyway,这个书至少给我打开了新世界的大门,hhhh 原来代码还可以这样玩.
当然这个框架还支持分布式服务 balabala的 具体就等大家去挖掘咯~

mac下 nvm use xxx后不生效

说明

安装了iterm2和oh my zsh, nvm也添加进入了.zshrc

1
2
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm

然后安装了nodejs 7.10.0版本后 新建iterm发现nodejs还是原来的v6.9版本…
试着删除了一下v6.9版本就报错了

1
N/A version is not installed yet

解决这个问题的办法很简单
github

不想看github的话那么就执行下面这个命令

1
nvm alias default 7.10.0

后面的7.10.0换成你的版本号.. 具体问题未深究….先解决再说

js开发总结

基层模块需要封装一层后才对外暴露

这里有个基层的,被封装为promise的基层函数/类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# request.js
function request(data){
return new Promise((resolve,reject)=>{
$.ajax({
data,
success(res){
resolve(res)
},
fail(res){
reject(res)
}
})
})
}
export{
request
}

同时我写了个登录函数,依赖于基层类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# login.js
import {request} from "request.js"
function login(user,pw){
request(user,pw)
.then((res)=>{
// get user info for token
return request(res.token)
})
.then((res)=>{
return Promise.resolve(res)
})
}

接着 我想要在每次调用接口的时候,假如接口返回401 那么试着让用户重新登录一次.
假如我日常调用的时候都是依赖于底层接口 那么就会产生一个循环引用问题

1
2
3
4
5
6
7
# a.js
request('get post list')
.then(()=>{
// 这里不需要我catch一次api返回401的问题 我想统一在基层request
.js函数处理. 那么问题就来了
})

login.js依赖request.js, request.js内部要做一次登录,这个登录又依赖于login.js
循环懵逼..

有个解决办法就是基层接口再次封装一层.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# ajax.js
function ajax(data){
return new Promise((resolve,reject)=>{
request(data)
.then((data)=>{
resolve(data)
}).catch(()=>{
//这里统一捕获到问题
login()
reject()
})
})
}

常用的js(nodejs)库整理

说明

本文为整理自己的github常用star. 免得到时候找个库都不知道找哪个.

本文包含了nodejs和js.可能还含有一些其他语言的库

详情的可以参考我githubStart

  • popper.js : 鼠标移上去的tips气泡提示
  • cleave.js : 格式化数据输出
  • http-proxy-middleware : express的http-proxy转发中间件
  • toolbar : 鼠标移上去的tips气泡提示
  • lightgallery.js : 画廊插件
  • fancybox : 画廊插件
  • PhotoSwipe : 画廊插件
  • csurf : express的csrf防御库
  • js-xss : 防止xss
  • cookie-parser : express的cookie解析
  • fks : 前端技能汇总
  • smoothscroll : 滚动插件 代替原生滚动
  • OwlCarousel2 : 幻灯片插件
  • localResizeIMG : 前端本地客户端压缩图片,兼容IOS,Android,PC
  • PhotoClip.js : 一款手势驱动的裁图插件
  • toolbox : 全栈工程师工具箱
  • sweetalert : alert的代替版提示框
  • progressbar.js : 加载进度条
  • pace : 滚动进度条提示
  • progress.js : 进度条插件
  • EaselJS : canvas库
  • TweenJS : 动画库
  • SoundJS : 针对声音的操控库
  • ios-imagefile-megapixel : ios图片压缩库
  • select2 : 多选插件
  • sticky : jquery滚动固定插件
  • validator.js : 轻量级的js验证插件
  • jquery-validation : jquery版的验证插件
  • bootstrap-modal : bootstrap-modal框插件
  • jQuery.mmenu : 左侧jquery导航栏插件
  • flexnav : 自适应导航栏插件
  • jQuery-menu-aim : jquery版的自适应导航栏插件
  • okayNav : 自适应导航栏插件
  • ScrollMagic : 视差滚动插件 比较强大 可制定化多
  • jquery.localScroll :jquery 视差滚动插件 参考域上和美
  • serverspeeder : 锐速破解版
  • gm : nodejs图形处理库
  • responsive-nav.js: 同响应式导航栏 但是没SlickNav好用
  • gulp-starter : gulp范例
  • shelljs : nodejs可以执行linux指令
  • fake2db : python测试数据库 压力测试
  • SlickNav : 响应式导航栏插件
  • notie : 屏幕内的通知插件
  • Caporal.js : nodejs快速生成命令行工具
  • Slideout.js : 移动端/pc端侧滑插件
  • node.bcrypt.js : nodejs加密插件
  • cdnjs-importer : 参考cdnjs.com这个库
  • csshake : css3抖动动画
  • countUp.js : 数字加载动画插件
  • bounce.js : js快速创建css3动画
  • dynamics.js : js物理引擎动画库
  • remote_inspect_web_on_real_device 各种真机远程调试方法汇总——“真机远程调试”
  • spy-debugger : 移动端手机调试插件
  • ms :毫秒互换/ 转换成秒/分/时 插件
  • web_js_css_frame : 前端框架合集介绍 –
  • ScrollTrigger : 滚动现实 Inview插件 比如进入某个div div需要做什么现实
  • Clusterize.js : 数据展示插件
  • Clamp.js : 多行文本溢出省略
  • dropload : 移动端上啦刷新 下拉加载插件
  • mobiscroll : 屌炸天的组件库…但是收费 价格忒贵
  • flatpickr : flat风格的日历选择插件,功能性比较强!
  • perfect-scrollbar: 简约但完美的自定义滚动条插件
  • Vconsole: weui的移动端console…某些特殊的环境下会出问题 比如某x付宝
  • iview : vue的组件库..类型与vux
  • weui.js :weui.io组件js库
  • jQuery-Parallax: jquery的鼠标滚动 页面视差滚动
  • jsdom: nodejs jsdom引擎
  • qart.js:前端快速生成二维码
  • cors: cors跨域处理问题
  • gulp-flatten: gulp扁平化组件 取消gulp层级目录 比如dev/js/a/x1.js => /dist/js/x1.js
  • iscroll: iscroll无限滚动库,注意其库只能有一个子组件 比如div>div1 但是不能有 div>div1+div2
  • request-promise:request promise版
  • VueCircleMenu: vue圆形菜单组件
  • ityped: js打字机效果
  • swagger-editor: api文档在线编写工具
  • jquery-weui: 微信ui库 jquery版本 如果同时引入weui,那么需要jquery-weui.css 覆盖weui的样式. 如果使用rem布局(flex)请覆盖jquery-weui的html(font-size) 同时对某些jquery-weui组件进行调整
  • weui: 微信ui库
  • particles.js:前端粒子库
  • normalizr:数据结构扁平化库
  • docsify:写文档用的库
  • conversational-form:像聊天一样填写biaodn
  • csspin:纯css写的loading动画
  • fecha:时间格式化库,跟moment.js一样,但是轻量功能少,用于微信小程序
  • Remodal:模态框弹出库
  • nprogress:页面顶部很细小的loading条
  • multer:nodejs的中间件,用来处理form-data
  • kcptun&&kcptun_gclient:kcptun架构相关库
  • colors.js:nodejs让你的命令行加上特效
  • pinyin:前端/nodejs汉字转拼音
  • json2csv:如名
  • webuploader:前端文件上传库
  • anyproxy:阿里出品的一款代理工具
  • sequelize:ORM查询mysql,关系型数据库,加快开发效率
  • stickUp:类似于fixed,根据滚动多少才fixed,可以用来做导航条
  • plax:视差滚动插件,推荐Parallax.js
  • scrollMonitor:视差滚动插件 滚轮滚动 .不同于plax
  • pm2:nodejs部署管理工具
  • Mock:后台没给数据之前伪造一份数据.加快开发效率
  • nightmare:封装过的PhantomJS.可以用来做浏览器访问
  • node-schedule:nodejs定时器工具
  • colour-schemes:各大IDE,编辑器的样式配置
  • store.js:封装好的前端存储localStorage,global等等
  • cropper:jquery图片裁剪插件
  • echo:图片lazyloading加载 懒加载
  • velocity:js动画库插件.增加了css3动画支持
  • casperjs:前端UI自动化测试框架
  • SVG-Loaders:SVG/css3 loading 加载动画
  • loaders.css:纯css的加载动画 loading
  • SpinKit:优雅高效的加载动画
  • device.js:判断目前访问的浏览器
  • stellar.js:4kstar的视差滚动 滚轮滚动
  • scrollpath:视差滚动,滚轮滚动.
  • WOW:滚动到某个div加载某个动画 依赖animate.css
  • jquery_lazyload:jquery的懒加载
  • scrollreveal:视差滚动,优雅高效
  • zoom.js:前端点击放大功能
  • reveal.js:前端做ppt的工具
  • nodePPT:前端做ppt的工具 国产
  • Parallax.js:最好的视差滚动插件,支持多个div视差滚动,通过!important来控制position不被覆盖
  • skrollr:视差滚动插件..加特效的
  • fastclick:处理移动端点击事件
  • mobileTech:移动端统计
  • purl&&URI.js:处理url查询参数
  • phantomjs&&phantomjs-node:nodejs中的浏览器
  • pageres&pageres-cli:nodejs截图插件
  • cheerio:nodejs dom解析库
  • node-crawler:封装好的爬虫..方便开发而已
  • SQLiScanner:sql注入查询
  • lib-flexible:淘宝flexible解决方案 利用rem
  • vux:vue.js 状态管理插件
  • validate.js:validate.js数据验证插件
  • nvm:nodejs版本管理工具
  • gitignore:git忽略文件库
  • plyr:html5 video库, 已经写好了样式,方便拿来使用
  • normalize.css:格式化浏览器
  • co:异步promise转为同步 yield
  • Waves:谷歌设计风格 点击按钮会有水波纹
  • CaptchaBundle:php验证码
  • css3d-engine:css3d引擎
  • videojs-contrib-hls:videojs中的hls转换
  • anime:js动画库
  • editor.md:前端markdown文本编辑器
  • OwlCarousel:前端滚动插件
  • gfwlist:防火墙list
  • sift.js:mongodb的语法查询json
  • electron-packager:electron打包工具

手把手教你如何利用nodejs+es6+co写一个爬虫

注意事项:

  1. 这里的爬虫不做太复杂的处理..

  2. 考虑到并发问题.这里的爬虫仅仅是爬完上一个后再爬下一个. 爬完当页后再去爬取下一页,效率虽然低..但是胜在不用同一时间发请大量请求避免被ban

  3. 本文以admin5.com为案例来爬取200页的文章title和content

  4. 本文涉及到的es6语法这里只会简单的说明一下.如果看不懂…来打我啊(笑)

涉及框架

crawler:为一个封装好的nodejs爬虫库,免去你用request框架发请请求然后处理一大堆的返回代码问题.本文只把crawler当做请求工具用.内容的处理将会用cheerio框架来完成

co:能够把异步代码写成跟同步一样,号称es6的async.

cheerio:nodejs版的jQuery

分析目标网站url

目标网站的url都是

1
http://www.admin5.com/browse/19/list_${i}.shtml

${i}<=965

那么这就好办了.生成965个链接然后每次去爬一个链接

分享目标网站DOM结构

目标网站的每篇文字的链接都在一个class为sherry_title的a标签里

1
<a href="http://www.admin5.com/article/20161209/700550.shtml" class="sherry_title" target="_blank">我是如何通过论坛推广产品的?</a>

那么每次爬的时候获取当页的所有文章链接然后再去爬取

文章内容DOM结构

标题放在一个class为sherry_title的div下的h1标签中

1
2
3
<div class="sherry_title">
<h1>我是如何通过论坛推广产品的?</h1>
</div>

内容则放在一个class为content的div标签中

1
2
<div class='content'>
</div>

那么内容中的图片如何爬取呢?
这个也简单…不过这篇文章暂时不说..哈哈哈哈哈

爬取分析

分析完目标网站后.那么就开始分析如何去爬.

  1. 封装一个获取html的Promise函数
  2. 封装一个获取目录的Promise函数
  3. 获取一个获取文章内容的Promise函数
  4. 开始爬取函数

爽爆天!加速翻墙,优化shadowsocks.让你的梯子飞起来

爽爆天!加速翻墙,优化shadowsocks.让你的梯子飞起来

本文参考了如下的几个教程

本文的服务器为centos7.0

安装shadowsocks至服务器

首先,关闭防火墙(centos 7.0)

1
2
systemctl disable firewalld.service
systemctl stop firewalld.service

centos6.9以下的可以参考

1
2
3
4
5
关闭命令: service iptables stop
永久关闭防火墙:chkconfig iptables off
两个命令同时运行,运行完成后查看防火墙关闭状态
service iptables status

1. 安装python

略,一般默认都带Python,如果不带那么谷歌/度娘一下

2. 安装pip,Python的包管理器

1
2
curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
$ python get-pip.py

3. 安装配置 shadowsocks

在控制台执行以下命令安装 shadowsocks:

1
2
pip install --upgrade pip
pip install shadowsocks

安装完成后,需要创建配置文件/etc/shadowsocks.json,内容如下:

1
2
3
4
5
6
{
"server": "0.0.0.0",
"server_port": 8388,
"password": "uzon57jd0v869t7w",
"method": "aes-256-cfb"
}

这里的server为服务器地址.可以填写127.0.0.1

server_port为你的shadowsocks端口

password为你的密码

method为你的加密方式 不理解的填写aes-256-cfb即可

4. 配置自启动

新建启动脚本文件/etc/systemd/system/shadowsocks.service,内容如下:

1
2
3
4
5
6
7
8
9
[Unit]
Description=Shadowsocks
[Service]
TimeoutStartSec=0
ExecStart=/usr/bin/ssserver -c /etc/shadowsocks.json
[Install]
WantedBy=multi-user.target

执行以下命令启动 shadowsocks 服务:

1
2
systemctl enable shadowsocks
systemctl start shadowsocks

为了检查 shadowsocks 服务是否已成功启动,可以执行以下命令查看服务的状态:

1
systemctl status shadowsocks -l

如果服务启动成功,则控制台显示的信息可能类似这样:

1
2
3
4
5
6
7
8
9
10
11
12
shadowsocks.service - Shadowsocks
Loaded: loaded (/etc/systemd/system/shadowsocks.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2015-12-21 23:51:48 CST; 11min ago
Main PID: 19334 (ssserver)
CGroup: /system.slice/shadowsocks.service
└─19334 /usr/bin/python /usr/bin/ssserver -c /etc/shadowsocks.json
Dec 21 23:51:48 morning.work systemd[1]: Started Shadowsocks.
Dec 21 23:51:48 morning.work systemd[1]: Starting Shadowsocks...
Dec 21 23:51:48 morning.work ssserver[19334]: INFO: loading config from /etc/shadowsocks.json
Dec 21 23:51:48 morning.work ssserver[19334]: 2015-12-21 23:51:48 INFO loading libcrypto from libcrypto.so.10
Dec 21 23:51:48 morning.work ssserver[19334]: 2015-12-21 23:51:48 INFO starting server at 0.0.0.0:8388

配置shadowsocks多用户

编辑/etc/shadowsocks.json文件

把原来的password字段改为port_password

每一个端口对应着一个用户名,后面的是密码

1
2
3
4
5
6
7
8
9
10
11
{
"server": "0.0.0.0",
"port_password": {
"8381": "foobar1",
"8382": "foobar2",
"8383": "foobar3",
"8384": "foobar4"
},
"timeout": 300,
"method": "aes-256-cfb"
}

重启服务

1
2
systemctl stop shadowsocks
systemctl start shadowsocks

安装KCP至服务器

1
2
3
4
5
wget https://raw.githubusercontent.com/kuoruan/kcptun_installer/master/kcptun.sh
chmod +x ./kcptun.sh
./kcptun.sh

其中需要注意的是

1.设置 Kcptun 的服务端端口:

请输入一个未被占用的端口,Kcptun 运行时将使用此端口。

2.设置加速的 IP:
Shadowsocks 就在运行在当前服务器上,直接回车即可。

3.设置需要加速的端口:这里为上一步安装shadowsocks的server_port中的端口

4.设置 Kcptun 密码: 这里推荐用自己设定的密码

如果安装成功,应该能看到如下输出信息:

1
2
3
4
5
6
7
8
9
10
11
12
恭喜, Kcptun Server 配置完毕!
服务器IP:  10.10.10.10
端口:  554
加速地址: 127.0.0.1:8388
加密方式 Crypt:  none
加速模式 Mode:  fast2

安卓手机开启KCP加速

首先安装shadowsocks在安卓上 这里的shadowsocks需要大于3.x

然后在KCP这一栏填写好KCP端口为你服务器上的端口

最重要的是KCP参数

1
--crypt aes --key 你的密码 --mode fast --mtu 1200 --autoexpire 60 --datashard 需要跟你服务器上的一致 --parityshard 需要跟你服务器上的一致

这里参考上述你服务器中的参数 然后添加进去即可

接着就享受爽快吧!!

电脑开启KCP加速

一步一步教你用Kcptun给Shadowsocks加速!看YouTube1080P一点都不卡!

只需要注意KCP参数

  • datashard –前向纠错
  • parityshard –前向纠错
  • nocomp –压缩
  • key –密钥
  • crypt –加密算法

保持这几个一致就好了 本地和服务器上的要一致. 这里的nocomp默认服务器是false 那么本地就不要去开启或者勾选

SEO实战密码-入门SEO

SEO常用指令

*通配

比如搜索某些词 李冰 那么中间的就代表通配符. 李力冰,李五冰 之类的都会出现在搜索词中

inurl

inurl用来搜索url中出现的关键词. 比如我的url是 http://baidu.com?a=我是搜索词
那么我搜索 inurl:我是搜索词 那么这个条目就会出现在搜索中。不过百度貌似已经不支持此搜索了

inanchor

搜索 inanchor:理财 的时候.
比如s网站有个a标签,里面的文字是理财 比如

1
<a href='http://c.com'>理财</a>

那么这条指令就是搜索的这种.研究c页面中的外链就可以找到很多链接资源,从而分析对方做了哪些SEO优化.

tips:百度不支持本条指令

intitle

搜索标题中的关键词.这条很简单就不说了,title一直是SEO很重要的因素,先会检查你title是否匹配然后才会去检查内容

1
intitle:xxx

allintitle

allintitle:soul 关键词

等同于

intitle:soul intitle:关键词

返回的页面即包括 soul 又包括 关键词

allinurl

与上述类似

filetype

用来搜索某些文件比如 filetype:pdf SEO
就会返回 包含SEO这个关键词的pdf

site

site用来搜索某个域名下的所有页面. 一般用来查询收录,但是不太准确,推荐还是用站长平台去查询

1
site:emufan.com

已经作废..

研究关键词

首先要做一个站点都需要去研究关键词,最重要的还是要确保你这个关键词会很火, 如果我把一个很偏门的关键词做到第一也没啥用- -别人不看.

细化关键词

比如做旅游,公司这两个关键词 不如去做 北京旅游,北京法律公司 这样细化的关键词 一方面比较好做,另一方面可能会带来隐藏的交易

长关键词

目前用户搜索并不是简简单单的搜索几个关键词了 有可能是很长的一种搜索,比如 前端工程师如何学习入门 而不是单纯的搜索 前端 入门
可以做一下长尾词的优化

内页排名

网站的首页通常是权重最高的.如果一个关键词多数为网站的内页,那么说明这个关键词还是可以去做的.因为对方首页并没有去优化此关键词. 那么你特定去优化还是有很大的把握去做到排名前的.

核心关键词

核心关键词要成金字塔结构.即 首页需要做网站主要的关键词 那么在内页就可以分散开来
也就是 首页可以放难度大的关键词 栏目/分类页 放难度次一级的 难度小的就放内页 形成一个金字塔结构

确立核心关键词

问题:

  • 你的网站能为用户解决什么问题
  • 用户遇到这些问题,会搜索什么关键词

竞争

  • 研究对手的SEO优化

搜索

  • 从谷歌关键词工具提炼出关键词
  • 通过百度指数搜索关键词
  • 通过谷歌趋势搜索关键词