前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C++屏幕截图 图片转JPEG

C++屏幕截图 图片转JPEG

作者头像
码客说
发布于 2021-07-13 03:22:17
发布于 2021-07-13 03:22:17
2.4K00
代码可运行
举报
文章被收录于专栏:码客码客
运行总次数:0
代码可运行

前言

C#实现同屏的时候,频繁截屏内存并不能很好的释放,所以就打算用C++实现这部分的功能。

这里图片的压缩用到了JpegLib, JpegLib是一个用C编写的jpeg图像压缩免费库,许多应用程序对jepg的支持都依赖于该库。

编译库

下载

下载地址:https://www.ijg.org/

官方下载地址:jpegsr9d.zip

百度云链接:https://pan.baidu.com/s/13xhEjxWR9b6Bx7OL6tLTIw 提取码:6owy

编译

使用Vistual studio的命令行工具进入源码文件夹

如图

注意

不要用系统的CMD或者Powershell,无法编译。

源码中复制一份jconfig.vc,改变后缀变为jconfig.h

执行如下命令

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
nmake -f makefile.vc

提示找不到win32.mak文件,在C盘搜索这个文件名,没有发现该文件,可以直接下一个

链接:https://pan.baidu.com/s/1y-uAsb5e6KdWFRgY3MxaKg 提取码:kn30 把·win32.mak放在源码目录下即可(Win10环境下需要下载)

编译成功后再项目下创建libjpeg文件夹,里面再创建includelib

把编辑后的libjpeg.lib放在lib目录下,所有的.h的头文件放在include

处理好的文件如下

链接:https://pan.baidu.com/s/1vEjL6CHgFDuqQioLq3dhJw 提取码:qeb3

项目下引用

项目下创建modules文件夹,把之前的libjpeg文件夹放进来

项目右键属性

C/C++常规中的附加包含目录中添加modules\libjpeg\include

链接器=>常规=>附加库文件中添加modules\libjpeg\lib

链接器=>输入=>附加依赖项中添加libjpeg.lib

这样项目中就可以调用了

Bmp2Jpeg.h

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#pragma once

class CBmp2Jpeg
{
public:
	CBmp2Jpeg();
	~CBmp2Jpeg();

public:
	int Bmp2Jpeg(const char* bmp, const char* jpeg);

private:
	int SaveJpeg(const char* filename, unsigned char* bits, int width, int height, int depth);
	int ReadBmp(const char* bmp, unsigned char** data, int& w, int& h, int& d);
	void Bgra2Rgb(const unsigned char* src, int w, int h, int d, unsigned char* dst);
	void InitFileHeader(void* pFile, void* fileHeader);
	void InitInfoHeader(void* pFile, void* infoHeader);
	void SaveBmp(void* fileHeader, void* infoHeader, int bitCount, unsigned char* data, const char* savename);
private:
	int	m_quality;	//它的大小决定jpg的质量好坏

	enum {
		JPEG_QUALITY = 100,
	};
};

Bmp2Jpeg.cpp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include<Windows.h>
#include <fstream>
#include <stdlib.h>
#include "Bmp2Jpeg.h"
#include <vector>

extern "C"
{
#include "jpeglib.h"
};

#pragma comment(lib,"libjpeg.lib")

using namespace std;

#pragma pack(2)

struct bmp_fileheader   //文件头,长度为14Byte固定
{
	unsigned short bfType;
	unsigned long bfSize;
	unsigned short bfReserved1;
	unsigned short bfReserved2;
	unsigned long bfOffBits;
};

struct bmp_infoheader  //文件信息头,长度为40Byte固定
{
	unsigned long biSize;
	unsigned long biWidth;
	unsigned long biHeight;
	unsigned short biPlanes;
	unsigned short biBitCount;
	unsigned long biCompression;
	unsigned long biSizeImage;
	unsigned long biXPelsPerMeter;
	unsigned long biYPelsPerMeter;
	unsigned long biClrUsed;
	unsigned long biClrImportant;
};

struct RGBPallete
{
	unsigned char b;
	unsigned char g;
	unsigned char r;
	unsigned char alpha;
};

CBmp2Jpeg::CBmp2Jpeg() :
	m_quality(JPEG_QUALITY)
{
}

CBmp2Jpeg::~CBmp2Jpeg()
{
}
/*===================================================================================
function:       jpeg压缩
input:          1:生成的文件名,2:bmp的指针,3:位图宽度,4:位图高度,5:颜色深度
return:         int
description:    bmp的像素格式为(RGB)
===================================================================================*/
int CBmp2Jpeg::SaveJpeg(const char* filename, unsigned char* bits, int width, int height, int depth)
{
	FILE* outfile;                 /* target file */
	fopen_s(&outfile, filename, "wb");
	if (outfile == NULL) {
		return -1;
	}

	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;

	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&cinfo);

	jpeg_stdio_dest(&cinfo, outfile);

	cinfo.image_width = width;      /* image width and height, in pixels */
	cinfo.image_height = height;
	cinfo.input_components = 3;         /* # of color components per pixel */
	cinfo.in_color_space = JCS_RGB;         /* colorspace of input image */

	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, m_quality, TRUE /* limit to baseline-JPEG values */);

	jpeg_start_compress(&cinfo, TRUE);

	JSAMPROW row_pointer[1];        /* pointer to JSAMPLE row[s] */
	int     row_stride;             /* physical row width in image buffer */
	row_stride = width * depth; /* JSAMPLEs per row in image_buffer */

	while (cinfo.next_scanline < cinfo.image_height) {
		//这里我做过修改,由于jpg文件的图像是倒的,所以改了一下读的顺序
		//row_pointer[0] = & bits[cinfo.next_scanline * row_stride];
		row_pointer[0] = &bits[(cinfo.image_height - cinfo.next_scanline - 1) * row_stride];
		(void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}

	jpeg_finish_compress(&cinfo);
	fclose(outfile);

	jpeg_destroy_compress(&cinfo);
	return 0;
}

void CBmp2Jpeg::InitFileHeader(void* pFile, void* fileHeader)
{
	bmp_fileheader* pfileHeader = (bmp_fileheader*)fileHeader;
	fstream* filein = (fstream*)pFile;
	//初始化文件头
	pfileHeader->bfType = 0;
	pfileHeader->bfSize = 0;
	pfileHeader->bfReserved1 = 0;
	pfileHeader->bfReserved2 = 0;
	pfileHeader->bfOffBits = 0;
	//读位图文件头并输出相应信息
	filein->read((char*)fileHeader, sizeof(bmp_fileheader));
}

void CBmp2Jpeg::InitInfoHeader(void* pFile, void* infoHeader)
{
	bmp_infoheader* pinfoHeader = (bmp_infoheader*)infoHeader;
	fstream* filein = (fstream*)pFile;
	//初始化信息头
	pinfoHeader->biSize = 0;
	pinfoHeader->biWidth = 0;
	pinfoHeader->biHeight = 0;
	pinfoHeader->biPlanes = 0;
	pinfoHeader->biBitCount = 0;
	pinfoHeader->biCompression = 0;
	pinfoHeader->biSizeImage = 0;
	pinfoHeader->biXPelsPerMeter = 0;
	pinfoHeader->biYPelsPerMeter = 0;
	pinfoHeader->biClrUsed = 0;
	pinfoHeader->biClrImportant = 0;

	//读位图信息头并输出相应信息
	filein->read((char*)infoHeader, sizeof(bmp_infoheader));
}

void CBmp2Jpeg::SaveBmp(void* fileHeader, void* infoHeader, int bitCount, unsigned char* data, const char* savename)
{
	bmp_fileheader* pfileHeader = (bmp_fileheader*)fileHeader;
	bmp_infoheader* pinfoHeader = (bmp_infoheader*)infoHeader;
	//写入文件
	std::string str(savename);
	str.append(".bmp");
	fstream fileout;
	fileout.open(str, std::ios::binary | std::ios::out);
	fileout.write((char*)fileHeader, sizeof(bmp_fileheader));
	fileout.write((char*)infoHeader, sizeof(bmp_infoheader));
	fileout.write((char*)data, sizeof(unsigned char) * pfileHeader->bfSize - pfileHeader->bfOffBits);

	fileout.close();
}

//读取并将图片另存为一个新文件, 转换成rgb格式
int CBmp2Jpeg::ReadBmp(const char* bmp, unsigned char** data, int& w, int& h, int& d)
{
	//打开位图文件
	fstream filein;
	filein.open(bmp, std::ios::binary | std::ios::in);
	if (!filein.is_open())
	{
		char clog[256] = { 0 };
		sprintf_s(clog, sizeof(clog), "bmp转jpeg,找不到 %s\n", bmp);
		OutputDebugStringA(clog);
		return -1;
	}

	//定义变量
	long width = 0;
	long height = 0;
	long bitCount = 0;

	bmp_fileheader  fileHeader;
	bmp_infoheader  infoHeader;

	InitFileHeader(&filein, &fileHeader);

	if (fileHeader.bfType != 0x4d42)
	{
		filein.close();
		return -1;
	}

	InitInfoHeader(&filein, &infoHeader);

	width = infoHeader.biWidth;
	height = infoHeader.biHeight;
	bitCount = infoHeader.biBitCount;

	int bitPerLine = ((width * bitCount + 31) >> 5) << 2;
	int imgSize = abs(height * bitPerLine);
	int imgReal = fileHeader.bfSize - fileHeader.bfOffBits;
	if (imgSize != imgReal)
	{
		char clog[256] = { 0 };
		sprintf_s(clog, sizeof(clog), "bmp转jpeg,图像尺寸不对\n");
		OutputDebugStringA(clog);
		filein.close();
		return -1;
	}

	if (bitCount == 8)
	{
		std::vector<RGBPallete> palletes;
		unsigned char buf[256 * sizeof(RGBPallete)];

		filein.read((char*)buf, 256 * sizeof(RGBPallete));

		for (int i = 0; i < 256; i++)
		{
			RGBPallete pallete;
			memcpy(&pallete, buf + i * sizeof(RGBPallete), sizeof(RGBPallete));

			palletes.push_back(pallete);
		}

		unsigned char* pTemp = new unsigned char[imgSize];
		filein.read((char*)pTemp, imgSize);

		*data = new unsigned char[width * abs(height) * 4];
		for (int i = 0; i < imgSize; i++)
		{
			RGBPallete& p = palletes[pTemp[i]];
			memcpy((*data) + i * sizeof(RGBPallete), &p, sizeof(RGBPallete));
		}

		bitCount = 32;
		delete pTemp;
	}
	else if (bitCount == 24 || bitCount == 32)
	{
		*data = new unsigned char[imgSize];
		filein.read((char*)(*data), imgSize);
		filein.close();
	}
	else
	{
		filein.close();
		return -1;
	}

	w = width;
	h = height;
	d = bitCount;

	return 0;
}

void CBmp2Jpeg::Bgra2Rgb(const unsigned char* src, int w, int h, int d, unsigned char* dst)
{
	unsigned char* pTempDst = dst;
	for (int i = 0; i < abs(h); i++)
	{
		const unsigned char* pTempSrc = nullptr;
		if (h > 0)
		{
			pTempSrc = src + w * i * d;
		}
		else
		{
			pTempSrc = src + w * abs(i + h + 1) * d;
		}

		for (int j = 0; j < w; j++)
		{
			*(pTempDst) = *(pTempSrc + 2);
			*(pTempDst + 1) = *(pTempSrc + 1);
			*(pTempDst + 2) = *(pTempSrc);
			pTempDst += 3;
			pTempSrc += d;
		}
	}
}

int CBmp2Jpeg::Bmp2Jpeg(const char* bmp, const char* jpeg)
{
	unsigned char* brga = nullptr; //指向位图buffer的全局指针,window下像素格式: BGRA(4个字节)
	int width = 0, height = 0, depth = 0;

	if (ReadBmp(bmp, &brga, width, height, depth) < 0)
	{
		return -1;
	}

	unsigned char* rgb = new unsigned char[width * abs(height) * depth / 8];
	Bgra2Rgb(brga, width, height, depth / 8, rgb);

	int ret = SaveJpeg(jpeg, rgb, width, abs(height), 3);

	delete[] brga;
	delete[] rgb;
	brga = nullptr;
	rgb = nullptr;
	return ret;
}

附录

截屏

ScreenShot.h

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#pragma once
bool ScreenShot(const char* szSavePath);

ScreenShot.cpp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>

#include <iostream>
using namespace std;

#pragma warning(disable:4996)

#define TAG_DEV_PLAS  1
#define BITS_PER_PIX  32
#define NO_COLOR_TAB  0
#define UNCMP_RGB     0
#define H_RESOL_0     0
#define V_RESOL_0     0
#define ALL_COLOR     0

#define MUST_ZERO     0
#define TYPE_BMP      0x4D42

#define FILE_HEAD     sizeof(BITMAPFILEHEADER)
#define INFO_HEAD     sizeof(BITMAPINFOHEADER)
#define HEAD_SIZE     sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER)

bool ScreenShot(const char* szSavePath)
{
	//显示器屏幕
	HDC hCurrScreen = GetDC(NULL);

	//创建一个兼容的DC,在内存中表示当前位图的上下文
	HDC hCmpDC = CreateCompatibleDC(hCurrScreen);

	//宽高
	int iScreenWidth = GetDeviceCaps(hCurrScreen, HORZRES);
	int iScreenHeight = GetDeviceCaps(hCurrScreen, VERTRES);

	//当前屏幕位图
	HBITMAP hBmp = CreateCompatibleBitmap(hCurrScreen, iScreenWidth, iScreenHeight);

	//用当前位图句柄表示内存中屏幕位图上下文
	SelectObject(hCmpDC, hBmp);

	//将当前屏幕图像复制到内存中
	BOOL ret = BitBlt(hCmpDC, 0, 0, iScreenWidth, iScreenHeight, hCurrScreen, 0, 0, SRCCOPY);

	//BMP图像信息头
	BITMAPINFOHEADER hBmpInfo;
	hBmpInfo.biSize = INFO_HEAD;
	hBmpInfo.biWidth = iScreenWidth;
	hBmpInfo.biHeight = iScreenHeight;
	hBmpInfo.biPlanes = TAG_DEV_PLAS;
	hBmpInfo.biClrUsed = NO_COLOR_TAB;
	hBmpInfo.biBitCount = BITS_PER_PIX;
	hBmpInfo.biSizeImage = UNCMP_RGB;
	hBmpInfo.biCompression = BI_RGB;
	hBmpInfo.biClrImportant = ALL_COLOR;
	hBmpInfo.biXPelsPerMeter = H_RESOL_0;
	hBmpInfo.biYPelsPerMeter = V_RESOL_0;

	/* * * * * * * * * * * * * * * * * * * *
	 * Windows按4字节分配内存
	 * 首先计算每行所需要的bit数,并按4字节对齐
	 * 对齐后的数据乘4,从DWORD转为BYTE
	 * 每行实际所占BYTE乘图像列数得到数据源大小
	 * * * * * * * * * * * * * * * * * * * */
	DWORD dwSrcSize = ((iScreenWidth * hBmpInfo.biBitCount + 31) / 32) * 4 * iScreenHeight;

	//截图总大小
	DWORD dwPicSize = HEAD_SIZE + dwSrcSize;

	//BMP图像文件头
	BITMAPFILEHEADER hBmpFile;
	hBmpFile.bfSize = dwPicSize;
	hBmpFile.bfType = TYPE_BMP;
	hBmpFile.bfOffBits = HEAD_SIZE;
	hBmpFile.bfReserved1 = MUST_ZERO;
	hBmpFile.bfReserved2 = MUST_ZERO;

	//BMP图像数据源
	char* bmpSrc = new char[dwSrcSize];
	ZeroMemory(bmpSrc, dwSrcSize);

	//检索指定的兼容位图中的所有位元数据
	//并复制到指定格式的设备无关位图的缓存中
	GetDIBits(hCmpDC, hBmp, 0, (UINT)iScreenHeight, bmpSrc, (BITMAPINFO*)&hBmpInfo, DIB_RGB_COLORS);

	//汇总所有数据信息
	char* szBmp = new char[dwPicSize];
	ZeroMemory(szBmp, dwPicSize);
	memcpy(szBmp, (void*)&hBmpFile, FILE_HEAD);
	memcpy(szBmp + FILE_HEAD, (void*)&hBmpInfo, INFO_HEAD);
	memcpy(szBmp + HEAD_SIZE, bmpSrc, dwSrcSize);

	//保存BMP图像
	FILE* hFile = fopen(szSavePath, "wb+");
	if (nullptr != hFile)
	{
		size_t count = fwrite(szBmp, 1, dwPicSize, hFile);
		fclose(hFile);
	}

	//释放资源
	DeleteObject(hBmp);
	DeleteObject(hCmpDC);
	ReleaseDC(NULL, hCurrScreen);
	delete[] szBmp;
	delete[] bmpSrc;
	szBmp = nullptr;
	bmpSrc = nullptr;
	return true;
}

调用

main.cpp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <stdio.h>
#include "Bmp2Jpeg.h"
#include "ScreenShot.h"
using namespace std;
int main()
{
	ScreenShot("D:\\pic\\2.bmp");
	CBmp2Jpeg bmp;
	bmp.Bmp2Jpeg("D:\\pic\\2.bmp", "D:\\pic\\2.jpeg");
	cout << "success." << endl;
	cin.get();
	return 0;
}

查看DLL方法

特别注意

生成DLL一定要用Release环境!!! 生成DLL一定要用Release环境!!! 生成DLL一定要用Release环境!!! 否则会依赖的DLL也会用Debug的DLL,在普通用户的环境中是没有这些DLL的。

现在我们要把方法导出

直接在原来的解决方案中添加项目,把之前的.cpp.h复制过来,然后导出方法就行了

screenshot.def

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
LIBRARY screenshot
EXPORTS
ScreenShot @1,
MyBmp2Jpeg @2,

注意

文件名和LIBRARY screenshot都要和项目名保持一致 导出都要导出方法,不要导出类,导出类其他语言不支持,所以我们添加一个导出方法MyBmp2Jpeg

MyBmp2Jpeg.cpp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <stdio.h>
#include "../Bmp2Jpeg.h"

int MyBmp2Jpeg(const char* bmp, const char* jpeg) {
	CBmp2Jpeg mbmp;
	mbmp.Bmp2Jpeg(bmp, jpeg);
	return 0;
}

同一个解决方案下dll会自动生成在debug目录下,所以dll不用再设置引用

调用方式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <stdio.h>
#include <Windows.h>

using namespace std;

int main()
{
	typedef bool (*ScreenShot)(const char* szSavePath);
	typedef int (*MyBmp2Jpeg)(const char* bmp, const char* jpeg);
	HINSTANCE hDLL;
	ScreenShot mScreenShot;
	MyBmp2Jpeg mBmp2Jpeg;
	hDLL = LoadLibrary(TEXT("screenshot.dll"));
	if (hDLL != 0) {
		mScreenShot = (ScreenShot)GetProcAddress(hDLL, "ScreenShot");
		mBmp2Jpeg = (MyBmp2Jpeg)GetProcAddress(hDLL, "MyBmp2Jpeg");
		mScreenShot("D:\\pic\\003.bmp");
		mBmp2Jpeg("D:\\pic\\003.bmp", "D:\\pic\\003.jpeg");
		cout << "success." << endl;
		cin.get();
		FreeLibrary(hDLL);//卸载dll文件;
	}
	return 0;
}

在VS目录中搜索dumpbin.exe,添加到环境变量中

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dumpbin /exports screenshot.dll

DLL导出类: 优点:导出的类可以被继承,调用层次也清晰,可以保留类的完整特性; 缺点:不能被其它语言调用(包括C语言),封装性并不是太好。

导出函数: 优点:可以被其它语言调用,使用简单,封装性相对较好; 缺点:调用层次不明显,尤其是在导出函数多的情况下,比较混乱,不能出现同名导出函数。

运行库

https://www.microsoft.com/zh-CN/download/details.aspx?id=48145

https://www.microsoft.com/zh-cn/download/details.aspx?id=26999

C#调用DLL方法

项目文件夹下创建DLLCPP文件夹,把screenshot.dll放进来

属性=>生成事件=>生成前事件命令行中添加

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
xcopy /Y /i /e $(ProjectDir)\DLLCPP $(TargetDir)\

页面中调用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[DllImport("screenshot.dll", EntryPoint = "ScreenShot", CallingConvention = CallingConvention.Cdecl)]
public extern static bool ScreenShot(string szSavePath);

[DllImport("screenshot.dll", EntryPoint = "MyBmp2Jpeg", CallingConvention = CallingConvention.Cdecl)]
public extern static int MyBmp2Jpeg(string bmp, string jpeg);

调用方式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ScreenShot("D:\\pic\\2.bmp");
MyBmp2Jpeg("D:\\pic\\2.bmp", "D:\\pic\\2.jpeg");
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-07-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
[seo优化]长尾词的理解与优化
一、 长尾关键词是什么?    一般大家对长尾关键词的理解是认为长尾关键词就是目标关键词的相关关键词。比如:    1)目标关键词是“养生茶”时,那么长尾关键词可以是“养生茶做法”、“养生茶大全”。    2)目标关键词是“旗袍”,那么长尾关键词可以是“旗袍美女”、“陈好旗袍”。    3)目标关键词是“法律”,那么长尾关键词可以是“法律咨询”,“法律讲堂”。    4)目标关键词是“nike”,那么长尾关键词可以是“nike air max 87”,“nike list”
Youngxj
2018/06/07
6680
网站SEO关键词布局核心优化策略
随着互联网的高速发展,越来越多的企业认识到了SEO优化对于品牌推广的重要性,作为一名合格的SEO站长,网站关键词排名上升是我们坚持不懈的驱动力。虽然说现在找一个SEOER并不困难,但是我们总是能够发现有的网站优化了一年了还是没有明显的效果,其实SEO优化并没有大家想的那么神奇,提高网站的关键词排名也并非很困难,只是我们需要将网站的优化工作做好就OK了。互联网上关于网站SEO关键词优化的帖子非常多,所以阿南今天也不分享什么挖掘关键词,网站定位这些入门的知识了,今天我们来讨论一下关键词布局的问题。
阿南SEO
2019/05/17
7160
网站SEO关键词布局核心优化策略
网站SEO优化步骤超详细完整版教程
一、准备 1、心态 长时间,不断学习。学习建站、基础代码、SEO全过程、实际操作并成功。
宜轩
2022/12/29
2.1K0
[SEO知识讲解] 揭秘大批量做“多个关键词快排技巧”
| 做SEO优化的人都知道,同一个关键词如果你排在竞争对手的前面,那么你的机会就更多。网站前期的策划也好,用户体验也好,都需要通过关键词,才能把真正的客户带到网站,变成实实在在的商机。这里,推广之家根
AlexTao
2019/12/13
1.3K0
谷歌关键词优化最佳实践
什么方法是谷歌关键词优化最好的?当我们面对着一个关键字列表,谷歌关键词排名优化怎么做效果好?要优化的关键词怎么放在网站才合适?很多人都知道把要优化的关键词放到网页,链接带上关键词并指向具体的网页,对于一般的关键词优化是可以的,如果要优化的关键词非常多,就需要考虑以下基本因素:
林雍岷
2019/07/03
6360
影响站内SEO关键词排名优化的几个因素
网站站内优化对于关键词排名优化工作来讲无疑是最重要的一部分,只有做好站内优化才能更加快速有效的提升排名。很多SEO在网站内部没有优化好之前就匆忙上线,上线之后又觉得关键词不合理、网站结构不合理,总之是喜欢在线反复调整。搜索引擎对这类网站降低印象分,会影响日后的SEO优化。
茹莱神兽
2021/05/22
7500
影响站内SEO关键词排名优化的几个因素
电商网站:关键词挖掘的4个策略!
对于任何网站而言,关键词是驱动流量增长最基本的元素,唯独不同的是电子商务网站需要的是更加精准的流量,因为这些关键词所肩负的责任与使命是达成销售目标,而与传统网站还是有一定区别的。 
蝙蝠侠IT
2019/07/11
1.1K0
电商网站:关键词挖掘的4个策略!
招聘网站排名,如何做好关键词优化?
关键词如果你有建立过门户网站的经历,你曾经一定建立过招牌栏目,当你的目标用户访问量逐渐升高的时候,你会发现利用站内目录做招牌站点,已经不能适用于业务的发展,于是大量的网站运营人员,开始将二级目录,转换成二级域名,而去全新的建立一个站点,去做招牌网站排名。
蝙蝠侠IT
2021/01/19
6840
招聘网站排名,如何做好关键词优化?
SEO人员,如何为博客添加关键词?
如果你对SEO稍微有一定的了解,在创建自己博客之初,你可能早已想好,要为自有的博客添加什么类型的关键词。
蝙蝠侠IT
2020/11/23
5880
SEO人员,如何为博客添加关键词?
优化企业网站不能仅靠SEO
这个不用过多解释了吧,就相当于做企业需要有自己的场地一样,企业应该有单独的一个企业站。  几年前做SEO的时候可能没有这个观念,因为之前人们对于网络不太了解,而互联网的开放程度加深,没有自己单独的企业网站,消费者对之信任度就会下降,成交率就会降低。  
雾海梦曦
2022/11/12
3710
如何做好单个关键词的排名优化?
接触过SEO外包公司的人都知道,单个关键词排名优化问题实际上是外包公司的核心业务。SEO盛行时代,SEO外包公司其实就是做关键词优化排名的,10个人左右,接单中小企业网站,主要优化的是首页关键词,3-5个关键词,一个个突击,从易到难,优化方法是从内到外,以下整理单个关键词排名优化方法作为参考。
茹莱神兽
2021/09/24
4490
如何做好单个关键词的排名优化?
为什么要关注长尾关键词?
专注于长尾关键词是一种很好的SEO策略。长尾关键词是比常用的关键词更具体的词或短语,长尾关键词具有较少的搜索量,但由于具有更具体的含义,因此通常具有较高的转化价值。它们使您可以逐渐吸引更多访问您网站的流量。
郝哥笔记
2021/03/31
4150
为什么要关注长尾关键词?
徐大大seo:利用SEO关键词工具完善产品谷歌关键词库
目前经过长期的外贸SEO经验,产品关键词库的建立在整个外贸网络营销中起着决定性的作用。当然关键词的获取来源是多方面的,我们主要针对的是Google搜索引擎。下面我们就讲一下如果利用Google关键词指数查询工具建立我们自己产品的关键词库。
徐大大seo
2022/05/17
4480
SEO优化:做好网站关键词优化应该怎么办?
  站长们开始做网站的时候就要考虑好seo网站排名的关键词,不仅是网站的title需要确定好关键词,同时长尾关键词也要考虑好,在选择关键词之前要适当的分析下关键词在搜索引擎中的竞争强度和指数,竞争太强的关键词就不要去做,可以选择相关的长尾关键词做排名。关键词确定好后,如果用的是wordpress程序,在后台直接添加网站标题就可以了,网站副标题是主关键词的描述,填写相关的关键词描述。这样网站的关键词就确定好了。
jinzhuseo.com-老牟
2018/08/01
4540
SEO优化:做好网站关键词优化应该怎么办?
百度快速收录SEO优化关键词排名优化技巧
前言:新站优化是有方法技巧的,关键词S排名优化,百度快速收录,新站如何快速出关键词排名,新站想要获取排名需要做好词库规划布局,做好文章内容优化,编写用户需求文章,做好更新和提交给百度站长,稳定持续操作优化推广,来做关键词排名优化
星泽V社
2022/03/02
1.5K0
[SEO知识讲解] 百度推出惊雷算法 SEO大神100条实战经验(一)
这是一篇翻译的文章,原作者是Brian Dean,一个很厉害的SEO工作者。他通过自身5年的SEO工作经验总结了100个经验教训,涉及了SEO各个方面的误区,写得很中肯。想看英文版本的,可以去文末找原文地址。以下是Brian Dean归纳的100个总结:
AlexTao
2019/11/14
1.3K0
外贸SEO该如何利用Google优化工具选择谷歌优化关键词
本文主要介绍了在外贸SEO优化中如何进行关键词选择,包括使用Google关键词规划师、分析关键词竞争度、确定核心和次核心关键词、制定关键词布局策略以及遵循关键词选择原则。这些方法对于提高外贸网站的搜索引擎排名和吸引潜在客户具有重要意义。
企鹅号小编
2018/01/09
1.1K0
外贸SEO该如何利用Google优化工具选择谷歌优化关键词
SEO之关键词的选择
选择恰当的关键词是SEO最具技巧性的环节之一。只有选择正确的关键词,才能使网站SEO走在正确的大方向上。确定什么样的关键词决定了网站内容规划、链接结构、外部链接建设等重要的后续步骤。在介绍选择关键词步骤前,我们先讨论选择关键词的原则。
海拥
2021/08/23
5430
为什么网站关键词数及SEO排名不稳定?
网站关键词是连接搜索引擎、网站以及用户的媒介,搜索引擎通过关键词判断网站页面的主题,用户通过关键词搜索进入网站获得想要的内容,而网站通过关键词布局优化获得搜索排名,带来流量转化变现,可见其重要性。
茹莱神兽
2022/03/22
3360
为什么网站关键词数及SEO排名不稳定?
SEO技巧:什么是长尾关键词,如何挖掘长尾关键词
长尾关键词是一个SEO必须考虑的因素,本文将和SEO新手简单谈谈何为长尾关键词,有什么作用?长尾词的挖掘方法有哪些?
星哥玩云
2022/08/13
7920
SEO技巧:什么是长尾关键词,如何挖掘长尾关键词
推荐阅读
相关推荐
[seo优化]长尾词的理解与优化
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验