301转向(或叫301重定向,301跳转)是当用户或搜索引擎向网站服务器发出浏览请求时,服务器返回的HTTP数据流中头信息(header)中的状态码的一种,表示本网页永久性转移到另一个地址。
其它常见的状态码还包括,200表示一切正常,404网页找不到,302暂时转向,等等。
使用 301 重定向将您原来网站上的所有网页永久重定向至新网站。 这可以告诉搜索引擎和用户您的网站已永久迁移。是符合搜索引擎友好的,目前最安全的网址域名更换。
请不要将原来网站的所有网页都定向到新网址的主页。虽然这样可以避免 404 错误,但并非良好的用户体验。建议将旧网址的网页对应到新网址同目录同名称的网页,网页对网页的重定向将有助于保持您的网站在 Google 上的排名,同时还能提供一种一致且直观的用户体验。
如果您新旧网站的网页无法一一对应,可尝试确保您原来网站上的每一个网页至少会重定向至一个具有相似内容的新网页。
301的另个重要用处是网址规范化。即选择你希望的唯一的首页网址。
301转向在seo中的作用
网址转向方法主要包括:301转向,302转向,JavaScript转向,PHP/ASP/CGI转向,META REFRESH网页META刷新,等。302转向可能会有URL规范化问题。其它方法都是常用的作弊手法,当然不是说不可以正当地用,方法本身没有错,但被作弊者用多了,搜索引擎对这些可疑的转向都很敏感。何必冒险呢。
当网页A用301重定向转到网页B时,搜索引擎可以肯定网页A永久的改变位置,或者说实际上不存在了,搜索引擎就会把网页B当作唯一有效目标。好处是,第一,没有网址规范化问题,第二,也很重要的,网页A的PR网页级别会传到网页B。
很多时候其它网站会链接到
http://domainname.com http://www.domainname.com/index.html http://domainname.com/index.html
而不是你希望的
http://www.domainname.com
这样链接的PR也会传递到所有URL,如果你用301转向把前三个URL转到
http://www.domainname.com
PR也就集中在网页http://www.domainname.com了。
如何实现301转向
用.htaccess实现301转向
文件及目录转向
比如把/old.htm转到http://www.domain.com/new.htm,可以用这个指令:
redirect 301 /old.htm http://www.domain.com/new.htm
或
redirect permanent /old.htm http://www.domain.com/new.htm
redirect也可以实现目录的转向,例如要将http://www.idcspy.com/bbs 转向到 http://bbs.idcspy.com 可以用: redirect 301 /bbs http://bbs.idcspy.com
规范www
全部统一到 www.zzbaike.com (带www)
RewriteEngine on
RewriteCond %{HTTP_HOST} ^zzbaike\.com$ [NC]
RewriteRule ^(.*)$ http://www.zzbaike.com/$1 [L,R=301]
使用时将上面的zzbaike.com 替换为你使用的域名即可
全部统一到 zzbaike.com (不带www,目前的新趋势)
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.zzbaike\.com$ [NC]
RewriteRule ^(.*)$ http://zzbaike.com/$1 [L,R=301]
使用时将上面的zzbaike.com 替换为你使用的域名即可
Rewrite实现301转向
RewriteEngine On
RewriteRule ^(.*)$ http://www.newdomain.com/ [R=301,L]
这个是都转向到新域名的首页
如果要做目录及文件转向用:
RewriteEngine On
RewriteRule ^(.*)$ http://www.newdomain.com/$1 [R=301,L]
上面的代码就可以将 http://www.idcspy.com/bbs/forum-51-1.html 这样类型的url转向到 http://bbs.idcspy.com/forum-51-1.html
PHP实现301重定向
在 index.php 的最上面加入以下几行:
<?php
header("HTTP/1.1 301 Moved Permanently");
header("Location: http://www.newdomain.com/");
exit();
?>
用PHP进行301重定向的坏处是无法进行目录的重定向
ASP实现301重定向
在 index.asp 或 default.asp 的最上面加入以下几行:
<% Response.Status="301 Moved Permanently" Response.AddHeader "Location","http://www.newdomain.com/" Response.End %>
静态网页实现301重定向
HTML无法做[htaccess]的301转向。在HTML里只能做JS或META REFRESH,但不是301转向。HTML一被读取,就已经返回200 OK状态码了。不过可以在主机商提供的工具里实现,登陆你的主机空间,进入cpanel(操作面板),找到“redirect”功能选项,填写将本网址指向其他网址。
举例: 1,如果是首页指向首页 http://www.aaa.com 指向 http://www.bbb.com 2,如果是网站内某一页指向首页 http://www.aaa.com/123344.htm 指向 http://www.bbb.com 3,指向相对应的新域名的同一目录下的文件名 http://www.aaa.com/123344.htm 指向 http://www.bbb.com/123344.htm 4, 把旧站的所有网页都指向首页 http://www.aaa.com/* 指向 http://www.bbb.com 5,把旧站的所有网页都指向新站相同目录相同名称的网页(即一一对应) http://www.aaa.com/* 指向 http://www.bbb.com/*
此种方法适用于动态网站和静态网站。
301重定向的后续工作
后续工作,登陆google网站管理,重新提交sitemap,头几次google可能因为发现访问旧站的的sitemap却进入另一个站sitemap,属于域名错误,提示网址不可用。报错。这个正常,再提交几次google就会发现301转向了,错误就会取消。在网站管理添加新站,提交新站的sitemap。选择搜索引擎按照有www或者无www来索引。(建议含www,同时无www也能访问)
过会去看看旧站的访问记录,就会发现 无论是访客,还是搜索引擎,进入网页都显示的是 http code 301。
成功。
建议旧站维持至少半年,之后再撤下。
- 监视注册表相关项的改变要用到一个API:RegNotifyChangeKeyValue。
- LONG RegNotifyChangeKeyValue(
- HKEY hKey, // 要监视的一个项的句柄
- BOOL bWatchSubtree, // 是否监视此项的子键
- DWORD dwNotifyFilter, // 监视哪些变化
- HANDLE hEvent, // 接受注册表变化事件的事件对象句柄
- BOOL fAsynchronous // 注册表变化前报告还是注册表变化后才报告
- );
- 注意上面的hEvent是接受注册表变化事件的事件对象句柄,我们要用API:
- CreateEvent来创建一个系统事件对象。
- HANDLE CreateEvent(
- LPSECURITY_ATTRIBUTES lpEventAttributes, // SECURITY_ATTRIBUTES结构
- BOOL bManualReset, // 是否自动重置
- BOOL bInitialState, // 是否设置初始状态
- LPCTSTR lpName // 事件对象的名称
- );
- 新建一个工程,添加一个ListBox,两个Button。
- //先写个监视注册表的例子
- //监视HKEY_CURRENT_USER\Software项下所有子键
- procedure TForm1.Button1Click(Sender: TObject);
- var
- hNotify : THandle;
- hKeyx : HKEY;
- dwRes : DWORD;
- begin
- hNotify := CreateEvent( nil, //不使用SECURITY_ATTRIBUTES结构
- FALSE, //不自动重置
- TRUE, //设置初始状态
- RegistryNotify //事件对象的名称
- );
- if hNotify = 0 then
- begin
- Showmessage(CreateEvent failed.);
- exit;
- end;
- if RegOpenKeyEx( HKEY_CURRENT_USER, //跟键
- Software, //子键
- 0, //reserved
- KEY_NOTIFY, //监视用
- hKeyx //保存句柄
- ) <> ERROR_SUCCESS then
- begin
- CloseHandle( hNotify );
- Showmessage(RegOpenKeyEx failed.);
- exit;
- end;
- if RegNotifyChangeKeyValue( hKeyx, //监视子键句柄
- TRUE, //监视此项的子键
- REG_NOTIFY_CHANGE_NAME or REG_NOTIFY_CHANGE_LAST_SET,
- hNotify, //接受注册表变化事件的事件对象句柄
- TRUE //注册表变化前报告
- ) <> ERROR_SUCCESS then
- begin
- CloseHandle( hNotify );
- RegCloseKey( hKeyx );
- Showmessage(RegNotifyChangeKeyValue failed);
- exit;
- end;
- dwRes := WaitForSingleObject( hNotify, 60 * 1000 ); //监视一分钟
- if dwRes = 0 then
- Showmessage( Registry will be changed. );
- CloseHandle( hNotify );
- RegCloseKey( hKeyx );
- end;
- 要注意的是,API: WaitForSingleObject要等到注册表变化事件发生或者超时才会
- 返回,在此期间我们的程序将失去响应。解决的办法是新建一个线程,在新线程中监视
- 注册表。
- 对注册表进行扫描要用到另外两个API: RegEnumKey和RegEnumValue。
- LONG RegEnumKey(
- HKEY hKey, // 要扫描的注册表项目句柄
- DWORD dwIndex, // 要扫描的subkey序号
- LPTSTR lpName, // 要扫描的subkey名称
- LPDWORD lpcbName, // 要扫描的subkey名称占用空间
- );
- 此函数的使用方法是: 首先给dwIndex赋值0, 调用RegEnumKey; 然后Inc(dwIndex),
- 再调用RegEnumKey,直到返回值为ERROR_NO_MORE_ITEMS,表示没有更多的子项了。
- //扫描注册表的例子
- //只演示了如何枚举HKEY_CURRENT_USER\Software下的一层子项
- procedure TForm1.Button2Click(Sender: TObject);
- var
- buf : array [0..255] of char;
- iRes : integer;
- hKeyx : HKEY;
- dwIndex, dwSize : DWORD;
- begin
- if RegOpenKeyEx( HKEY_CURRENT_USER, Software, 0, KEY_READ or
- KEY_ENUMERATE_SUB_KEYS, hKeyx ) <> ERROR_SUCCESS then
- begin
- Showmessage(RegOpenKeyEx failed.);
- exit;
- end;
- dwIndex := 0;
- repeat
- dwSize := 255;
- iRes := RegEnumKey( hKeyx, dwIndex, buf, dwSize );
- if iRes = ERROR_NO_MORE_ITEMS then
- break
- else if iRes = ERROR_SUCCESS then
- begin
- Listbox1.Items.Add( buf );
- Inc( dwIndex );
- end;
- until iRes <> ERROR_SUCCESS;
- RegCloseKey( hKeyx );
- end;
- procedure TForm1.Button1Click(Sender: TObject);
- var
- SearchRec : TSearchRec;
- Path : String;
- Attr : integer;
- Found : integer;
- begin
- Path := 'c:\*.*';//设定要显示的路径
- Attr := faAnyFile;
- Found := FindFirst(Path, Attr, SearchRec);//查找文件
- while Found = 0 do
- begin
- ListView1.Items.Add; //添加内容
- ListView1.Items[ListView1.Items.Count-1].Caption := (SearchRec.Name);
- Found := FindNext(SearchRec);
- end;
- FindClose(SearchRec);//停止查找
- end;
位于Standard选项卡上,它是对EDIT控件的扩展,可以对多行文本进行显示、输入
和编辑.
Lines属性:
该属性实际上为TStrings类型的对象,用来存放Memo对象的文本
TStrings有一个缺省的属性Strings,它的定义为:
property strings[index:integer]:string;
其中,Index表示字符串的索引值,从0开始,到TStrings对象中字符串的最大行
数减1为止。
TStrings的主要方法:
procedure add(const s:string);//在尾部添加一个字符串
procedure delete(index:integer);//删除索引值为INDEX的字符串
procedure insert(index:integer;const s:string);//在INDEX位置处插入一个
字符串
procedure clear;//清除所有的字符串
procedure loadfromfile(const filename:string);//从文本文件中装载字符串
组
procedure savetofile(const filename:string);//将字符串组存为一个文件
由于属性Lines的类型为TStrings,所以了解了TStrings的主要属性和方法后,就
可以使用Lines属性组管理Memo的文本了
memo1.lines[0]:='this is first line';//将首行的内容改为 'this is first
line'
memo1.lines.add('add line');//在最后添加一行,内容为 'add line'
memo1.lines.delete(0);//将第一行删除
memo1.lines.insert(1,'inert one line');//在第二行处添加
memo1.lins.loadfromfile('c:\readme.txt');//从文本文件中装载字符串组
Text属性:
该属性的类型为字符串型,内容为Memo的文本,该属性与Lines的不同之处在于它
是一个字符串存放了Memo的所有内容。
MaxLength属性:
该属性用来确定Memo所能接受的最大字符数,缺省时为0,表示不限制
WordWrap属性:
该属性用来设置Memo的文本是否可以自动换行。如果设为TRUE,则文本可以自动
换行,同时应将水平滚动条设为无效。
Modified属性:
该属性用来确定文本是否被改动过,如果为TRUE,则表示被改动过
SelText属性:
该属性可以用来获得被选中的文本
SelLength属性:
该属性可以用来获得被选中的文本的长度
- //增加项或列(字段)
- ListView1.Clear;
- ListView1.Columns.Clear;
- ListView1.Columns.Add;
- ListView1.Columns.Add;
- ListView1.Columns.Add;
- ListView1.Columns.Items[0].Caption:='id';
- ListView1.Columns.Items[1].Caption:='type';
- ListView1.Columns.Items[2].Caption:='title';
- ListView1.Columns.Items[2].Width:=300;
- Listview1.ViewStyle:=vsreport;
- Listview1.GridLines:=true; //注:此处代码也可以直接在可视化编辑器中完成,
- 也可写成以下这样
- begin
- with listview1 do
- begin
- Columns.Add;
- Columns.Add;
- Columns.Add;
- ViewStyle:=vsreport;
- GridLines:=true;
- columns.items[0].caption:='进程名';
- columns.items[1].caption:='进程ID';
- columns.items[2].caption:='进程文件路径';
- Columns.Items[0].Width:=100;
- Columns.Items[1].Width:=100;
- Columns.Items[2].Width:=150;
- end
- end;
- //增加记录
- with listview1.items.add do
- begin
- caption:='1212';
- subitems.add('hh1');
- subitems.add('hh2');
- end;
- //删除
- listview1.items.delete(0);
- //从数据库表里读取数据写入Listview
- var
- Titem:Tlistitem; //此处一定要预定义临时记录存储变量.
- begin
- ListView1.Items.Clear;
- with adoquery1 do
- begin
- close;
- sql.Clear;
- sql.Add('select spmc,jg,sl from kcxs');
- Open;
- ListView1.Items.Clear;
- while not eof do
- begin
- Titem:=ListView1.Items.add;
- Titem.Caption:=FieldByName('spmc').Value;
- Titem.SubItems.Add(FieldByName('sl').Value);
- Titem.SubItems.Add(FieldByName('jg').Value);
- next;
- end;
- //删除
- ListView1.DeleteSelected;
- //如何取得ListView中选中行的某一列的值
- procedure TForm1.Button2Click(Sender: TObject);
- begin
- ShowMessage(ListView1.Selected.SubItems.Strings[1]); //返回选中行第三列中的值
- end;
- showMessage(listView1.Selected.Caption); //返回选中行第一列的值.
- 第1列的值: -->>> ListView1.Selected.Caption
- 第i列的值(i>1):-->>> ListView1.Selected.SubItems.Strings[i]
- ListView1.Items.Item[1].SubItems.GetText); //取得listview某行某列的值
- Edit2.Text := listview1.Items[i].SubItems.strings[0]; //读第i行第2列
- 返回选中行所有子列值.是以回车符分开的,你还要从中剥离出来你要的子列的值。
- showMessage(ListView1.Selected.SubItems.GetText);
- ListView 简单排序的实现
- ListView 排序
- 怎样实现单击一下按升序,再单击一下按降序。
- function CustomSortProc(Item1, Item2: TListItem; ColumnIndex: integer): integer; stdcall;
- begin
- if ColumnIndex = 0 then
- Result := CompareText(Item1.Caption,Item2.Caption)
- else
- Result := CompareText(Item1.SubItems[ColumnIndex-1],Item2.SubItems[ColumnIndex-1])
- end;
- procedure TFrmSrvrMain.ListView1ColumnClick(Sender: TObject;
- Column: TListColumn);
- begin
- ListView1.CustomSort(@CustomSortProc,Column.Index);
- end;
- ===============================================================
- //增加
- i := ListView1.Items.Count;
- with ListView1 do
- begin
- ListItem:=Items.Add;
- ListItem.Caption:= IntToStr(i);
- ListItem.SubItems.Add('第 '+IntToStr(i)+' 行');
- ListItem.SubItems.Add('第三列内容');
- end;
- //按标题删除
- for i:=ListView1.Items.Count-1 downto 0 Do
- if ListView1.Items[i].Caption = Edit1.Text then
- begin
- ListView1.Items.Item[i].Delete(); //删除当前选中行
- end;
- //选中一行
- if ListView1.Selected <> nil then
- Edit1.Text := ListView1.Selected.Caption;
- // listview1.Items[Listview1.Items.Count -1].Selected := True;
- // listview1.Items[Listview1.Items.Count -1].MakeVisible(True);
- procedure TForm1.Button2Click(Sender: TObject); // 选择第一条
- begin
- listview1.SetFocus;
- listview1.Items[0].Selected := True;
- end;
- procedure TForm1.Button1Click(Sender: TObject); // 选择最后一条
- begin
- listview1.SetFocus;
- listview1.Items[Listview1.Items.Count -1].Selected := True;
- end;
- //这是个通用的过程
- procedure ListViewItemMoveUpDown(lv : TListView; Item : TListItem; MoveUp, SetFocus : Boolean);
- var
- DestItem : TListItem;
- begin
- if (Item = nil) or
- ((Item.Index - 1 < 0) and MoveUp) or
- ((Item.Index + 1 >= lv.Items.Count) and (not MoveUp))
- then Exit;
- lv.Items.BeginUpdate;
- try
- if MoveUp then
- DestItem := lv.Items.Insert(Item.Index - 1)
- else
- DestItem := lv.Items.Insert(Item.Index + 2);
- DestItem.Assign(Item);
- lv.Selected := DestItem;
- Item.Free;
- finally
- lv.Items.EndUpdate;
- end;
- if SetFocus then lv.SetFocus;
- DestItem.MakeVisible(False);
- end;
- //此为调用过程,可以任意指定要移动的Item,下面是当前(Selected)Item
- ListViewItemMoveUpDown(ListView1, ListView1.Selected, True, True);//上移
- ListViewItemMoveUpDown(ListView1, ListView1.Selected, False, True);//下移
- TListView组件使用方法
- 引用CommCtrl单元
- procedure TForm1.Button1Click(Sender: TObject);
- begin
- ListView_DeleteColumn(MyListView.Handle, i);//i是要删除的列的序号,从0开始
- end;
- 用LISTVIEW显示表中的信息:
- procedure viewchange(listv:tlistview;table:tcustomadodataset;var i:integer);
- begin
- tlistview(listv).Items.BeginUpdate; {listv:listview名}
- try
- tlistview(listv).Items.Clear;
- with table do {table or query名}
- begin
- active:=true;
- first;
- while not eof do
- begin
- listitem:=tlistview(listv).Items.add;
- listitem.Caption:=trim(table.fields[i].asstring);
- // listitem.ImageIndex:=8;
- next;
- end;
- end;
- finally
- tlistview(listv).Items.EndUpdate;
- end;
- end;
- ListView使用中的一些要点。以下以一个两列的ListView为例。
- →增加一行:
- with ListView1 do
- begin
- ListItem:=Items.Add;
- ListItem.Caption:='第一列内容';
- ListItem.SubItems.Add('第二列内容');
- end;
- →清空ListView1:
- ListView1.Items.Clear;
- →得到当前被选中行的行的行号以及删除当前行:
- For i:=0 to ListView1.Items.Count-1 Do
- If ListView1.Items[i].Selected then //i=ListView1.Selected.index
- begin
- ListView1.Items.Delete(i); //删除当前选中行
- end;
- 当然,ListView有OnSelectItem事件,可以判断选择了哪行,用个全局变量把它赋值出来。
- →读某行某列的操作:
- Edit1.Text := listview1.Items[i].Caption; //读第i行第1列
- Edit2.Text := listview1.Items[i].SubItems.strings[0]; //读第i行第2列
- Edit3.Text := listview1.Items[i].SubItems.strings[1]; //读第i行第3列
- 以次类推,可以用循环读出整列。
- →将焦点上移一行:
- For i:=0 to ListView1.Items.Count-1 Do
- If (ListView1.Items[i].Selected) and (i>0) then
- begin
- ListView1.SetFocus;
- ListView1.Items.Item[i-1].Selected := True;
- end;
- 不过在Delphi6中,ListView多了一个ItemIndex属性,所以只要
- ListView1.SetFocus;
- ListView1.ItemIndex:=3;
- 就能设定焦点了。
- Delphi的listview能实现交替颜色么?
- procedure TForm1.ListView1CustomDrawItem(
- Sender: TCustomListView; Item: TListItem; State: TCustomDrawState;
- var DefaultDraw: Boolean);
- var
- i: integer;
- begin
- i:= (Sender as TListView).Items.IndexOf(Item);
- if odd(i) then sender.Canvas.Brush.Color:= $02E0F0D7
- else sender.Canvas.Brush.Color:= $02F0EED7;
- Sender.Canvas.FillRect(Item.DisplayRect(drIcon));
- end;





