Search engine-friendly URLs

话题不得不从很早前就开始,原来的论坛 ( http://oldbbs.netbuddy.org/cgi-bin/ultrabo...d/ultraboard.pl ) 用的是UltraBoard 2000,如果用Google查询,可能会查到旧论坛的首页,其它的页面Google上无法找到,为什么呢?
因为无论用什么论坛,基本上论坛都是由动态生成的页面组成的,而且论坛都有认证功能,一般来说,访问某个主题的连接可能是这样的:
http://oldbbs.netbuddy.org/cgi-bin/UltraBo...15&TID=636&SID=

这里面有很多Google等搜索引擎所不喜欢的符号,比如&,?,=等等,Google等搜索引擎最喜欢的就是静态的HTML页面了(比如 http://mize.netbuddy.org/ 那种),Google最讨厌的就是"ID=0DCB19209AE0"这样的字符串,因为类似这样字符串都是被一些动态页面(比如 postnuke/phpnuke、各种论坛等)用来表示一个session的,也许Google用来INDEX站点的蜘蛛(spider)——Googlebot每次访问某个动态页面的同一个页面时URL中的ID=都会不同。

比如
http://oldbbs.netbuddy.org/cgi-bin/UltraBo...15&TID=636&SID=
http://oldbbs.netbuddy.org/cgi-bin/UltraBo...636&SID=0292381

访问的是同一个页面

所以,Google等搜索引擎是最恨&,?,=这样的字符了,更讨厌ID=XXXX这样的字符串出现在某个URL里面,如果某个URL包含大量的这样的字符,那么Google可能会拒绝INDEX这个页面。

这也是很多论坛的主题很难从Google上搜索到的原因,这也是xxbin下定决心要把论坛的URLs改成搜索引擎友好的最直接原因和动力,要知道自己的贴子如果能够从Google上Search到那是多么开心的一件事情啊! biggrin.gif

首先我们来分析一下我们的论坛的URLs:
http://bbs.netbuddy.org/index.php?act=ST&f...=4&t=403&arch=0

这个联结是xxbin登陆论坛后访问网络论坛中"Google正在INDEX我们的论坛"这张贴子时的URL

这个URL对Google来说最严重的莫过于URL中包含的""这样的字符串了,这个东东Google看见了肯定就不再理我们了,需要去掉,测试了一下,可能是因为cookie的原因,登陆用户不用""这样的字符串也能正常访问论坛,同时论坛也能够识别这个用户,这样的话最重要的问题就解决了。 smile.gif

URL可能变成这样:
http://bbs.netbuddy.org/index.php?act=ST&f...=4&t=403&arch=0

接下来就是&,?,=等等Google不喜欢的字符串了,如果我们能够把上面的URL转换成
http://bbs.netbuddy.org/index/act/ST/f/4/t/403/arch/0

那Google就会喜欢我们了! biggrin.gif

怎么转
首先,在根目录下建立一个index文件,内容如下:
CODE

<?php

require "conf_global.php";
$base_url = $INFO['board_url']."/index.php";  

$redirect = "";

if ( $_SERVER['PATH_INFO'] != "" )
{
       $c = 0;
       $redirect = "?";
       foreach( explode( "/", $_SERVER['PATH_INFO'] ) as $bit)
       {
               if ($bit != "")
               {
                       if ($c == 0)
                       {
                               $c++;
                               $redirect .= $bit.'=';
                       }
                       else
                       {
                               $c = 0;
                               $redirect .= $bit.'&';
                       }
               }
       }
}

header("Location: $base_url".$redirect);

exit();

?>



稍微懂一点php或者c的语法的人都能看出来,这个脚本是把类似
http://bbs.netbuddy.org/index/act/ST/f/4/t/403/arch/0
这样的URL重定向到
http://bbs.netbuddy.org/index.php?act=ST&f...=4&t=403&arch=0

我们的HTTP Server是Apache 2.0.43
在Apache 1.x版本,对于
http://bbs.netbuddy.org/index/act/ST/f/4/t/403/arch/0
的URL,首先apache会查找是否存在/index这样一个目录,若这个目录不存在,那么查找是否存在/index这样一个文件,如果存在这个文件,就把后面的字符串作为参数传递给/index这个文件,而Apache 2.0.43就改了一下,如果没有/index这个目录,那么就报404错误。 sad.gif 为了解决这个问题xxbin可在Google上查了很久,最后发现在Apache 2.0.43的配置文件中加入AcceptPathInfo On就可以解决这个问题。

最后,为了让apache知道这个没有任何扩展名的index文件是个php脚本,需要在配置文件或者.htaccess文件中加入下面的配置:

<Files index>
ForceType application/x-httpd-php
</Files>

重起apache之后,发现用http://bbs.netbuddy.org/index/act/ST/f/4/t/403/arch/0的连接可以正常访问论坛了,接下来的工作就是把论坛首页,论坛索引,贴子列表等等页面的连接从原来Google不喜欢的格式改成Search engine-friendly URLs,OK,大功告成!

(注:因为index脚本用的是Redirect,因此各位在地址栏看到论坛的连接还是那种Google讨厌的格式,但是论坛的真实联结(移动鼠标到某个联结,然后从状态栏看到的连接)基本上已经改成Search engine-friendly URLs了)
1. 安装Elasticsearch和Python Elasticsearch客户端 - Elasticsearch安装可以参考官网的[安装文档](https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html) - Python Elasticsearch客户端可以使用pip安装:`pip install elasticsearch` 2. 在Django项目中创建一个app,用于处理与Elasticsearch相关的逻辑。 3. 配置Elasticsearch连接信息,可以在Django的`settings.py`中添加以下配置: ``` ELASTICSEARCH_DSL = { 'default': { 'hosts': 'localhost:9200' }, } ``` 其中,`hosts`就是Elasticsearch的地址,这里使用默认的`localhost:9200`。 4. 创建Elasticsearch索引模板,可以在app目录下创建一个`search_indexes.py`文件,定义索引模板: ``` from elasticsearch_dsl import Document, Text, Date, Keyword class ArticleIndex(Document): title = Text() content = Text() pub_date = Date() tags = Keyword(multi=True) class Index: name = 'articles' ``` 其中,`ArticleIndex`是一个继承自`Document`的类,定义了索引的字段和类型。`Index`类中的`name`属性指定了索引的名称。 5. 在app目录下创建`serializers.py`文件,定义序列化器,将模型序列化为Elasticsearch索引模板: ``` from rest_framework import serializers from .models import Article from .search_indexes import ArticleIndex class ArticleIndexSerializer(serializers.ModelSerializer): class Meta: model = Article fields = ('id', 'title', 'content', 'pub_date', 'tags') def save(self, **kwargs): article = super().save(**kwargs) article_index = ArticleIndex(meta={'id': article.id}, **article.__dict__) article_index.save() return article ``` 其中,`ArticleIndexSerializer`继承自`ModelSerializer`,定义了序列化的模型和字段。在`save`方法中,先保存模型,再将模型数据序列化为Elasticsearch索引模板,最后保存到Elasticsearch中。 6. 在app目录下创建`views.py`文件,定义视图函数,实现Elasticsearch搜索功能: ``` from rest_framework.views import APIView from rest_framework.response import Response from elasticsearch_dsl import Q from .search_indexes import ArticleIndex from .serializers import ArticleIndexSerializer class ArticleSearchView(APIView): def get(self, request): query = request.query_params.get('q', '') s = ArticleIndex.search().query( Q('multi_match', query=query, fields=['title', 'content', 'tags']) ) response = [] for hit in s.execute().hits: serializer = ArticleIndexSerializer(data=hit.to_dict()) serializer.is_valid() response.append(serializer.data) return Response(response) ``` 其中,`ArticleSearchView`继承自`APIView`,定义了一个`get`方法,接收`q`参数作为搜索关键词。通过Elasticsearch DSL构建查询语句,搜索索引模板中的数据,最后将搜索结果序列化返回。 7. 在app目录下创建`urls.py`文件,定义路由: ``` from django.urls import path from .views import ArticleSearchView urlpatterns = [ path('search/', ArticleSearchView.as_view(), name='article_search'), ] ``` 其中,`search`路由对应了`ArticleSearchView`视图函数。 8. 在Django的`settings.py`中添加app,配置数据库信息: ``` INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'app_name', # 添加app ] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'db_name', 'USER': 'db_user', 'PASSWORD': 'db_password', 'HOST': 'localhost', 'PORT': '3306', } } ``` 9. 在app目录下创建`models.py`文件,定义模型,使用Django ORM作为数据源: ``` from django.db import models class Article(models.Model): title = models.CharField(max_length=255) content = models.TextField() pub_date = models.DateTimeField(auto_now_add=True) tags = models.CharField(max_length=255, blank=True) def __str__(self): return self.title ``` 其中,`Article`是一个继承自`models.Model`的类,定义了文章的属性。 10. 在app目录下创建`admin.py`文件,注册模型到Django Admin中: ``` from django.contrib import admin from .models import Article admin.site.register(Article) ``` 11. 在Django的`urls.py`中添加app的路由: ``` from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('app_name.urls')), ] ``` 12. 启动Django开发服务器,访问`http://localhost:8000/admin/`,进入Django Admin,创建一些文章数据。 13. 访问`http://localhost:8000/api/search/?q=django`,可以看到搜索结果,其中包含关键词`django`的文章数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值