核心方法:seo分析竞争对手常用到的软件总结.docx
优采云 发布时间: 2022-10-31 22:21核心方法:seo分析竞争对手常用到的软件总结.docx
seo分析大赛常用软件汇总
今天总结一下SEO过程中分析竞争对手常用的软件,在此分享给小伙伴们。在SEO过程中,我们经常分析我们的竞争对手。分析离不开数据采集、整理、分析三个环节。在做数据分析的时候,最常用的软件就是SEOseo分析大赛。常用软件总结
今天总结一下SEO过程中分析竞争对手常用的软件,在此分享给小伙伴们。在SEO过程中,我们经常分析我们的竞争对手。分析离不开数据采集、整理、分析三个环节。在做数据分析时,最常用的软件是SEO Assistant、SEO Companion、SEO Quick Catcher、Linkdust。几个软件
. 这些软件中经常用到的功能如下:
1. 搜索引擎优化助手
目的:关键词排名批量查询
本软件一般使用标准版,此版本为付费版,售价88元。总的来说,价格还可以。相信任何从事SEO的同胞都可以消费。除了标准版,还有另外两个正式版。低的
终端的共享版和高端的专业版。一般情况下,标准版配合其他软件使用,功能就足够了。
SEO助手的主要功能是批量查询网站的关键词排名(我个人认为网站的关键词排名在某些情况下过于频繁行业高于网站>有一定的负面影响),因为需要跟踪的关键词排名有上千甚至上万,对比了几款SEO软件后,我最终选择了SEO完成这项工作。配合SEO助手,可以实现批量关键词导入、跟踪、报表导出。相信对于一些门户网站来说已经足够了,后面会进行统计分析。
工作是手动计算和分析的。
应该说,SEO不仅在批量关键词排名分析方面做得很好,其他一些功能也开发得比较好。
2. SEO伴侣
目的:查询关键词竞争分析
这是一个很小的SEO软件,小到几百K。
黑白非常喜欢这个软件的“关键词竞争对手分析”功能。通过SEO Companion,可以分析百度和谷歌的竞争水平关键词,并且有非常直观友好的输出界面,让关键词的竞争一目了然。输出数据包括URL、关键词密度、PR、SR、外链数量、标题内容、关键词内容、描述、收录体积、alexa、域名注册日期。结合这些级别比赛的分析对比结果,我相信
对SEO稍有了解的朋友可以发现自己网站与竞争对手的差距,以及网站在优化过程中的不足。
3. SEO快速捕手
用途:批量查询网站收录的数量
同样,这也是一个很小的软件,主要目的是批量查询网站的收录个数。对于从事门户网站或内容丰富的网站的SEO朋友来说,是一款非常不错的收录查询软件。
SEO快手可百度查询网站
操作方法:Linux中对【库函数】的调用进行跟踪的 3 种【插桩】技巧
目录
目录
别人的经验,我们的阶梯!
什么是仪表?
在规模不大的代码(C语言)中,调用第三方动态库中的函数来完成一些功能是很常见的工作场景。
假设现在有一个任务:在调用动态库中的函数之前和之后需要做一些额外的处理。
这样的需求一般称为:instrumentation,也就是对于一个指定的目标函数,我们新建一个wrapper函数来完成一些附加的功能。
在包装函数中调用真正的目标函数,但是在调用之前或之后,你可以做一些额外的事情。
例如:统计函数的调用次数,验证函数的输入参数是否合法等等。
关于程序插桩的官方定义,可以看【百度百科】中的描述:
Program Instrumentation 最早由 JC Huang 教授提出。
就是在保证被测程序原有逻辑完整性的基础上,在程序中插入一些探针(也称为“探针”),本质上是信息采集的代码段,可以是赋值语句或 采集 覆盖信息的函数调用)。
通过probe的执行,抛出程序运行的特征数据,通过对这些数据的分析,可以得到程序的控制流和数据流信息,进而得到逻辑覆盖率等动态信息,从而达到测试目的的方法。
根据探针插入的时间,可以分为目标代码插桩和源代码插桩。
在这篇文章中,我们一起来讨论一下:在Linux环境下的C语言开发中,有哪些方法可以实现instrumentation功能。
Instrumentation 示例代码分析
示例代码很简单:
├── app.c
└── lib
├── rd3.h
└── librd3.so
假设动态库librd3.so是第三方提供的,里面有一个函数:int rd3_func(int, int);。
// lib/rd3.h
#ifndef _RD3_H_
#define _RD3_H_
extern int rd3_func(int, int);
#endif
在应用程序 app.c 中,调用了动态库中的这个函数:
app.c 的代码如下:
#include
#include
#include "rd3.h"
int main(int argc, char *argv[])
{
int result = rd3_func(1, 1);
printf("result = %d n", result);
return 0;
}
编译:
$ gcc -o app app.c -I./lib -L./lib -lrd3 -Wl,--rpath=./lib
-L./lib:指定编译时搜索lib目录下的库文件。
-Wl,--rpath=./lib:指定执行时搜索lib目录下的库文件。
生成可执行程序:app,执行:
$ ./app
result = 3
示例代码非常简单,可以称为 helloworld 的兄弟版本!
在编译时检测
检测函数的基本要求是不对原创文件 (app.c) 进行额外修改。
由于 app.c 文件已经收录“rd3.h”,因此调用了 rd3_func(int, int) 函数。
所以我们需要创建一个假的“rd3.h”提供给app.c,并将函数rd3_func(int, int)“重定向”到一个封装函数,然后在封装函数中调用真正的目标函数,如下如图所示:
“重定向”功能:可以使用宏来实现。
Wrapper函数:新建一个C文件,在这个文件中,需要#include "lib/rd3.h",然后调用真正的object文件。
完整的文件结构如下:
├── app.c
├── lib
│ ├── librd3.so
│ └── rd3.h
├── rd3.h
└── rd3_wrap.c
最后两个文件是新创建的:rd3.h、rd3_wrap.c,其内容如下:
// rd3.h
#ifndef _LIB_WRAP_H_
#define _LIB_WRAP_H_
// 函数“重导向”,这样的话 app.c 中才能调用 wrap_rd3_func
#define rd3_func(a, b) wrap_rd3_func(a, b)
// 函数声明
extern int wrap_rd3_func(int, int);
<p>
#endif
</p>
// rd3_wrap.c
#include
#include
// 真正的目标函数
#include "lib/rd3.h"
// 包装函数,被 app.c 调用
int wrap_rd3_func(int a, int b)
{
// 在调用目标函数之前,做一些处理
printf("before call rd3_func. do something... n");
// 调用目标函数
int c = rd3_func(a, b);
// 在调用目标函数之后,做一些处理
printf("after call rd3_func. do something... n");
return c;
}
让 app.c 和 rd3_wrap.c 一起编译:
$ gcc -I./ -L./lib -Wl,--rpath=./lib -o app app.c rd3_wrap.c -lrd3
头文件的搜索路径不能错:必须在当前目录下搜索rd3.h。在这种情况下,app.c 中的#include "rd3.h" 会找到新的头文件 rd3.h。
所以在编译指令中,第一个选项是-I./,意思是搜索当前目录下的头文件。
另外,由于#include "lib/rd3.h"用于在rd3_wrap.c文件中收录库中的头文件,所以编译指令中不需要指定lib目录来查找头文件。
编译得到可执行程序app,执行:
$ ./app
before call rd3_func. do something...
after call rd3_func. do something...
result = 3
完美的!
链接舞台仪表
Linux 系统中的链接器功能非常强大,它提供了一个选项:--wrap f,可以在链接阶段进行插桩。
该选项的作用是告诉链接器遇到f符号时解析为__wrap_f,遇到__real_f符号时解析为f,正好是一对!
我们可以利用该属性新建一个文件rd3_wrap.c,并定义一个函数__wrap_rd3_func(int, int),并在该函数中调用__real_rd3_func函数。
只要将 -Wl,--wrap,rd3_func 添加到编译选项中,编译器就会:
将app.c中的rd3_func符号解析成__wrap_rd3_func,调用包装函数;
将 rd3_wrap.c 中的 __real_rd3_func 符号解析为 rd3_func 以调用真正的函数。
这些符号的转换是由链接器自动完成的!
按照这个思路,我们一起来测试一下。
文件目录结构如下:
.
├── app.c
├── lib
│ ├── librd3.so
│ └── rd3.h
├── rd3_wrap.c
└── rd3_wrap.h
rd3_wrap.h被app.c引用,内容如下:
#ifndef _RD3_WRAP_H_
#define _RD3_WRAP_H_
extern int __wrap_rd3_func(int, int);
#endif
rd3_wrap.c 的内容如下:
#include
#include
#include "rd3_wrap.h"
// 这里不能直接饮用 lib/rd3.h 中的函数了,而要由链接器来完成解析。
extern int __real_rd3_func(int, int);
// 包装函数
int __wrap_rd3_func(int a, int b)
{
// 在调用目标函数之前,做一些处理
printf("before call rd3_func. do something... n");
// 调用目标函数,链接器会解析成 rd3_func。
int c = __real_rd3_func(a, b);
<p>
// 在调用目标函数之后,做一些处理
printf("after call rd3_func. do something... n");
return c;
}
</p>
在 rd3_wrap.c 中,不能直接收录“rd3.h”,因为 lib/rd3.h 中的函数声明是 int rd3_func(int, int); 没有 __real 前缀。
编译它:
$ gcc -I./lib -L./lib -Wl,--rpath=./lib -Wl,--wrap,rd3_func -o app app.c rd3_wrap.c -lrd3
注意:这里的头文件搜索路径仍然设置为-I./lib,因为这个头文件收录在app.c中。
要获取可执行程序 app,请执行:
$ ./app
before call rd3_func. do something...
before call rd3_func. do something...
result = 3
完美的!
执行阶段仪表
在编译阶段,新创建的文件rd3_wrap.c与app.c一起编译,包装函数名为wrap_rd3_func。
函数的“重定向”通过app.c中的宏定义实现:rd3_func --> wrap_rd3_func。
我们也可以直接“霸王”:在新创建的文件rd3_wrap.c中,直接定义rd3_func函数。
然后在这个函数中,通过dlopen、dlsym系列函数动态打开真实的动态库,查找里面的object文件,调用真实的object函数。
当然,这种情况下,编译app.c的时候,lib/librd3.so文件是不能链接的。
继续练习这个想法!
文件目录结构如下:
├── app.c
├── lib
│ ├── librd3.so
│ └── rd3.h
└── rd3_wrap.c
rd3_wrap.c文件内容如下(暂时忽略一些错误检查):
#include
#include
#include
// 库的头文件
#include "rd3.h"
// 与目标函数签名一致的函数类型
typedef int (*pFunc)(int, int);
int rd3_func(int a, int b)
{
printf("before call rd3_func. do something... n");
//打开动态链接库
void *handle = dlopen("./lib/librd3.so", RTLD_NOW);
// 查找库中的目标函数
pFunc pf = dlsym(handle, "rd3_func");
// 调用目标函数
int c = pf(a, b);
// 关闭动态库句柄
dlclose(handle);
printf("after call rd3_func. do something... n");
return c;
}
编译包装好的动态库:
$ gcc -shared -fPIC -I./lib -o librd3_wrap.so rd3_wrap.c
获取包装好的动态库:librd3_wrap.so。
要编译可执行程序,需要链接包装库 librd3_wrap.so:
$ gcc -I./lib -L./ -o app app.c -lrd3_wrap -ldl
要获取可执行程序 app,请执行:
$ ./app
before call rd3_func. do something...
after call rd3_func. do something...
result = 3
完美的!
- - - 结尾 - - -
文中的测试代码已经放在网盘上。
在公众号【IOT物联网小镇】后台回复关键词:220109,即可获取下载地址。
原创不易,请多多支持道哥,分享文章给更多嵌入式朋友,谢谢!