python可以写web网站吗_使用 python 开发 Web Service – IBM Developer

本文已归档

归档日期:: 2020-02-14此内容不再被更新或维护。 内容是按“原样”提供。鉴于技术的快速发展,某些内容,步骤或插图可能已经改变。

搭建开发环境

一个基本的 python web service 开发环境由以下这些工具组成:

Python2.4,Eclipse WTP,PyDev plug-in,Python ZSI包。

安装 python2.4

Python2.4 可以在网站,下载安装包,安装过程非常简单,在此不再赘述。

安装 Eclipse WTP

安装 pyDev

在 http://pydev.sourceforge.net/download.html 下载 pyDev 插件,解压后将 features 目录和 plugin 目录下的所有文件都拷贝到 Eclipse 的相同目录下就可以了。本文中使用的是 release1.3.9。

安装 python ZSI

从 ZSI 的网站上下载最新的安装包,在写这篇文章的时候,最新的 ZSI 版本为 2.0。解压缩后运行如下命令:

figure1.GIF

ZSI 还依赖与一些其它的 python 开源包:SOAPpy,pyXML。本文在后面列出了它们的下载地址。必须安装这些 python 包 ZSI2.0 才能正常运行。

本文提供的 Web service 描述

在本文中我们将利用 python 提供几个 web service,然后用 Java 客户端调用它们。作为演示,我们仅设计了三个简单的 web service:

getTime():返回代表当前时间的字符串。没有输入参数。

sayHello(username):返回一个字符串,内容为”Hello username”,其中 username 为传入参数。

showUser(username):根据输入的 username 返回一个复杂数据类型 userInfo,描述用户的年龄,性别,联系地址。

创建工程

首先创建一个工程。打开 Eclipse,选择 File->New Project。当 pyDev 插件安装好后,会有一个 pyDev project 的选项。选择该选项并创建一个 pyDev 工程。

编写 wsdl 文件

Wsdl 是一个 XML 文件,它主要用来描述所提供的网络服务的细节。用户通过 wsdl 文件就可以了解您所提供的网络服务的调用接口的所有细节。

感谢 Eclipse WTP 提供的 WSDL Editor,它使得编写 WSDL 文件变成了一件轻松的事情。WSDL Editor 提供了可视化的编辑界面。利用 WSDL Editor,用户可以完全从服务本身来思考,无需深入了解 WSDL 的细节。

首先要在工程中增加一个 WSDL 文件,点击菜单 File->New 选择 Other,在弹出的对话框中选择WSDL文件。如下图所示:

figure2.GIF

单击 next,给新文件命名为 myServices.wsdl。选择缺省选项并点击 finish 按钮就会生成一个缺省的空 wsdl 文件。此时,将看到如下所示的编辑界面:

figure3.GIF

缺省的 WSDL 包含了三个部分 Service,Binding 和 operation。对于一般的应用,只需修改 operation,即上图中最右边的方框。为了提供前面所描述的三个网络服务,我们需要在这个方框中增加三个新的 operation。

第一个网络服务是 getTime。将缺省 wsdl 文件的 operation 方框中的第一个表项修改一下,就可以完成 getTime 的定义了。首先单击标题 NewOperation,将名字高亮选中,如下图所示:

figure4.GIF

将其重新命名为 getTime。getTime 服务没有入口参数。但有一个返回值,我们定义返回值为一个表示时间的字符串。注意图二中方框外右边的两个箭头,双击它们就可以分别进入定义入口和出口参数的窗口。首先双击 Input 后面的箭头 (上图中用红色圆圈标出),可以进入如下图所示的参数定义窗口:

figure5.GIF

在新打开的 Inline Schema of myServices.wsdl 窗口中,我们可以设置 getTime 的入口参数。getTime 不需要入口参数,因此将缺省的入口参数 in 删除:

figure6.GIF

关闭新打开的窗口,回到图一所示的 wsdl 编辑界面。双击 getTime 的 output 后面的箭头,定义返回值。将缺省的返回值名字 out 修改为 timeStr,类型 string,不需要改变:

figure7.GIF

这样 getTime 就设计好了。下面回到主窗口,添加 sayHello 的定义。在 Operation 方框上单击鼠标右键,选择 Add Operation:

figure8.GIF

同样,双击方框右边的箭头,分别设置其入口参数和返回值。sayHello 的入口参数为字符型,名字为 username。返回值也是 string 类型。

添加新的 operation,命名为 showUser。这个服务的入口参数也是用户名,类型为 string,但是它的返回值是一个复杂类型。用 WSDL Editor 可以方便地定义复杂类型。进入返回值设计窗口(双击 output 后的箭头),在 element 上单击鼠标右键,弹出菜单中选择 Set Type->New。在弹出对话框中选择 Complex Type,并将新类型命名为 userInfo。

在eclipse的outline 窗口中选中 types->userInfo,定义 userInfo。

figure9.GIF

主窗口显示出 userInfo 的设计界面,鼠标右键单击 userInfo,选择弹出菜单的 add element,增加三个 string 类型的元素 name, gender 和 address。如下图所示:

figure10.GIF

现在可以存盘了,三个服务都已经设计好。下一步,我们将用 python ZSI 提供的脚本处理 WSDL 文件,并生成服务代码框架。

编写 web service 服务端代码

ZSI 包提供了两个脚本用来根据 wsdl 文件生成相应的 server 端和 client 端的 python 代码框架。下面的命令生成 server 端代码:

figure11.GIF

脚本 wsdl2py 的 -b 选项会生成一些辅助代码,后面的描述中将会看到这些辅助代码能简化编程。运行以上两条命令后,会生成三个文件:

myServices_services.py , myServices_services_server.py , myServices_services_types.py

这三个 python 文件就是服务端的代码框架。为了提供最终的 web 服务,我们还需要添加一个文件,用来实现每个 web 服务的具体代码。将新文件命名为 serviceImpl.py(完整的源代码可以在文章最后下载)。仅实现 getTime 的 serviceImpl.py 如下:

from myServices_services_server import *

from time import time,ctime

from ZSI.ServiceContainer import AsServer

class mySoapServices(myServices):

def soap_getTime(self,ps):

try:

rsp = myServices.soap_getTime(self, ps)

request = self.request

rsp.set_element_timeStr(ctime())

except Exception, e:

print str(e)

return rspShow moreShow more icon

首先导入 myServices_services_server,它是由 wsdl2py 脚本生成的 Web 服务框架代码。类 myServices 是 web 服务的基础类,每一个 web 服务都对应其中的一个方法。getTime 对应 myServices 类中的 soap_getTime 方法。缺省的 soap_getTime 方法只是一个基本框架,但完成了 soap 解析并且能返回该服务的入口参数对象。

为了实现 getTime,我们需要重载 soap_getTime 方法。定义新类 mySoapServices,继承自 myServices。在 mySoapServices 类中重载父类的 soap_getTime() 方法。

getTime 的主要功能是返回一个表示当前时间的字符串。python 系统函数 ctime,就可以得到当前的系统时间。重载 soap_getTime() 函数中,首先调用父类的 soap_getTime() 方法,得到返回值对象rsp。

调用返回值对象 rsp 的 set_element_xxx() 方法,就可以对返回值对象中的元素进行赋值。这个方法是由 wsdl2py 的 -b 选项生成的。

set_element_timeStr(ctime()) 将返回值的 timeStr 元素赋值为代表当前时间的字符串。

sayHello() 的代码与此类似。但是与 getTime 不同,sayHello 服务还需要处理客户端调用时传入的入口参数。sayHello 方法的源代码:

def soap_sayHello(self,ps):

try:

rsp = myServices.soap_sayHello(self,ps)

request = self.request

usrName = request.get_element_userName()

rsp.set_element_helloStr("Hello "+usrName)

except Exception, e:

print str(e)

return rspShow moreShow more icon

request 代表入口参数对象。对于 sayHello 服务,入口参数只有一个元素 userName。调用 request 对象的 get_element_userName() 方法就可以得到该元素的值。

调用返回值对象 rsp 的 set_element_helloStr 将返回字符串赋值给 helloStr 元素。

showUser 服务与前面两个服务的不同在于返回值是一个复杂对象,该复杂对象在 python 中可以用下面这个类来表示:

class userInfo:

def __init__(self,nm,gen,addr):

self.name = nm

self.gender = gen

self.address = addrShow moreShow more icon

showUser 服务根据客户端传入的用户名在数据库中查找该用户的详细信息并填充 userInfo 对象,相应代码如下:

def soap_showUser(self,ps):

try:

rsp = myServices.soap_showUser(self,ps)

request = self.request

uName = request.get_element_userName()

userDetail = rsp.new_user()

nm=self.users[uName].name

userDetail.set_element_name(nm)

gender=self.users[uName].gender

userDetail.set_element_gender(gender)

addr=self.users[uName].address

userDetail.set_element_address(addr)

rsp.set_element_user(userDetail)

except Exception, e:

print str(e)

return rspShow moreShow more icon

调用 request 对象的 get_element_userName 方法得到入口参数,并赋值给 uName。然后在数据库中查找用户uName的详细信息,将详细信息填充到 userInfo 类对象中,并返回。作为演示,我们并没有真的到数据库中查询,而是在内存中建立一个字典:

u1 = userInfo("u1","M","Shanghai")

u2 = userInfo("u2","F","Beijing")

self.users={}

self.users["u1"]=u1

self.users["u2"]=u2Show moreShow more icon

该字典中有两个用户:u1 和 u2。演示代码在该字典中查询用户,将查选结果返回用户。

调用 rsp 对象的 new_element_user() 方法创建一个新的返回对象,并用 userDetail 保存。

调用 userDetail.set_element_gender 将用户性别信息设置到返回值对象的 gender 元素中。同样方法设置用户名和地址。

最后将新建的 userDetail 对象设置到返回值 rsp 中:rsp.set_elememnt_user(userDetail)。

发布 web service

所有 web 服务代码都已经写好了,需要服务器代码来发布它们。在复杂并且有较高要求的应用环境中,用户可能需要用 apache 等强大的 web server 来发布 web services。限于篇幅,本文不打算介绍如何在 apache 上发布 python web services。本文将使用 ZSI 自带的 SOAP server。

正如下图所示,使用 ZSI soap server 只需要很少的几行代码:

from ZSI.ServiceContainer import AsServer

from serviceImpl import mySoapServices

from ZSI import dispatch

if __name__ == "__main__":

port = 8888

AsServer(port,(mySoapServices('test'),))Show moreShow more icon

这段代码无需太多解释。port 定义了 web service 发布的端口号。ZSI 包的 AsServer 方法只有两个参数:一个是端口;另外一个是包含了 web 服务实现代码的类,在我们的实验中就是 mySoapServices。字符串 test,表示 web 服务发布时的虚拟路径。当上述代码成功运行之后,就会在 localhost 上开启一个 web server,并在端口 8888 发布 myServices 服务。一切都非常简单,体现了用 python 语言的最吸引人的特点,快速而强大!

我们将在本机访问 myServices,相应的 URL 为 http://localhost/test?wsdl。

编写 java 客户端

现在我们使用 eclipse 集成环境来开发 web services 的客户端程序,调用前面章节描述的那些 web services。

Eclipse 提供了一个简单的方法来创建 web service 应用程序,即 Web Service Wizard。

首先创建一个 Web Project。

打开 File->New->Other…->Dynamic Web Project,创建一个新的工程。

figure12.GIF

然后就可以创建 java 客户端。选择 File -> New -> Other… -> Web Services -> Web Service Client

figure12.GIF

选择 Next,在下一个窗口中的 Service Definition 中填写相应的 webservice 的发布地址 URL。在本文中为: http://localhost:8888/test?wsdl

figure12.GIF

选择 Finish 按钮。将自动生成 java 代码。包括以下几个文件: MyService_PortType.java MyService_Service.java MyService_ServiceLocatior.java MyServiceProxy.java MyServiceSOAPStub.java

另外 showUser() 返回一个复杂对象,所以 eclipse 还创建了一个 java 类表示该复杂对象类,文件名为 UserInfo.java

作为测试,我们写了一个 java 小程序,调用 getTime。

import org.example.www.myService.MyServiceProxy;

public class HelloClient {

public static void main(String[] args){

try {

System.out.println("Step1");

MyServiceProxy hello = new MyServiceProxy();

System.out.println("Step2");

java.lang.String str = hello.getTime();

System.out.println("step over");

System.out.println(str);

}

catch (Exception ex)

{

System.out.println(ex.getMessage());

}

}

}Show moreShow more icon

sayHello 和 showUser 的调用代码与上面的示例类似。

结束语

用 Eclipse 的 WTP 开发 WSDL 文件,用 python 实现 Web 服务都比较简单而快速。用这两个强大的工具能够迅速地开发 Web 服务应用,适用于原型产品的快速开发。 这样就能抓住先机,比对手更快的推出新的Web应用,从而在市场上立于不败之地。

weixin_39624774
关注 关注
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用python+ZSI开发 Web Service环境搭建
05-24
使用python+ZSI开发 Web Service环境搭建说明文档
完整项目:IBM Full Stack Cloud Developer专业证书项目
02-20
适用于数据科学的Kubernetes和OpenShift Python,适用于AI和应用程序的Python开发适用于AI和应用程序开发Python项目使用微服务和无服务器全栈云开发Capstone项目使用SQL,数据库和Django应用程序开发应用程序
pythonwebservice_用python客户端去访问webservice
weixin_39943799的博客
12-05 170
在前几篇文章里面我重点用python去发布一个webservice。我用的是soaplib库。发布以后确实可以通过php来访问,也可以通过python访问,通过php访问的话还好。但是通过python访问的时候必须知道服务端的代码,这一点从官方给出的demo可以看出,这就比较烦人。所以我改用另外的一个python 库 :sudssuds下载安装很简单,这里就不说了。这里我想一下它是怎么用的。我们...
Python开发WebService
yang5915的专栏
08-15 4015
WebService是一种跨编程语言和跨操作系统平台的远程调用技术。 理解WebService 1.从表面上看,WebService就是一个应用程序向外界暴露出一个能通过Web进行调用的API,也就是说能用编程的方法通过Web来调用这个应用程序。我们把调用这个WebService的应用程序叫做客户端,而把提供这个WebService的应用程序叫做服务端。 2.从深层次看,WebServi...
python 开发webservice
xyddd的博客
05-31 253
https://blog.csdn.net/weixin_42516007/article/details/112324926
Python 开发与测试 Webservice(SOAP)-Win
杰儿__er 的博客
06-10 4637
1.从表面上看,WebService就是一个应用程序向外界暴露出一个能通过Web进行调用的API,也就是说能用编程的方法通过Web来调用这个应用程序。我们把调用这个WebService的应用程序叫做客户端,而把提供这个WebService的应用程序叫做服务端。2.从深层次看,WebService是建立可互操作的分布式应用程序的新平台,是一个平台,是一套标准。它定义了应用程序如何在Web上实现互操作性,你可以用任何你喜欢的语言,在任何你喜欢的平台上Web service ,只要我们可以通过Web servi
使用 GAN生成时尚图像,无需编单行代码_python_代码_下载
06-15
训练了大量的深度学习模型,用于对 Fashion MNIST 数据集(https://developer.ibm.com/patterns/train-a-model-on-fashion-dataset-using-tensorflow-with-ffdl/)进行分类。如果训练数据集可以增加更多图像,则可以...
python-sdk:客户端库,可在Python使用IBM Watson服务,并在pip中以watson-developer-cloud的形式提供
02-03
Watson Developer Cloud Python SDK Python客户端库,可快速开始使用各种服务。 目录 公告! 从watsonplatform.net更新端点URL watsonplatform.net上的Watson API端点URL正在更改,并且在2021年5月26日之后将无法...
node-red-dsx-workflow:此过程有助于使用IBM Watson Studio构建完整的端到端分析解决方案。 此存储库包含创建自定义Web界面的指令,以触发Jupyter Notebook中的Python代码执行并在IBM Watson Studio上可视化来自Jupyter Notebook的响应
02-04
node-red-dsx-workflow:此过程有助于使用IBM Watson Studio构建完整的... 此存储库包含创建自定义Web界面的指令,以触发Jupyter Notebook中的Python代码执行并在IBM Watson Studio上可视化来自Jupyter Notebook的响应
IBM-Full-Stack-Cloud-Developer
03-08
IBM Full Stack Cloud开发人员 作者:郑德贤 状态:〜ing 创建该存储库是为了跟踪Coursera提供的 。 该教育程序是由IBM开发的,旨在教授如何在cloud computing环境中进行编程。 该专业证书将为您提供所有关键技能...
python调用webservice接口的实现
09-19
主要介绍了python调用webservice接口的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
python调用WEBSERVICE接口
07-12
python调用WEBSERVICE接口
Python调用WebService接口实例说明
09-26
Python调用WebService接口实例
Python调用webservice
Heyll__的博客
05-31 2293
import suds from suds.client import Client from suds.xsd.doctor import Import, ImportDoctor url= "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl" imp= Import('http://www.w3.org/200...
python开发webservice例子
程序猿的专栏
03-17 1209
服务器段代码: import soaplib from soaplib.core.server import wsgi from soaplib.core.service import DefinitionBase from soaplib.core.service import soap from soaplib.core.model.clazz import Array f
Python服务器发布webservice
OnlyLove_longshao的博客
06-02 551
webservice服务器端实例代码 # -*- coding utf-8 -*- # import socket import json from spyne import Application, rpc, ServiceBase, Array, Integer, Unicode from spyne.protocol.soap import Soap11 from spyne.server.wsgi import WsgiApplication class CarConditionServ
webService开发
shaowei213的专栏
06-21 315
1.定义一个类 2.将这个类的方法给外界调用, 在里面加上发布的服务的代码 public static void main(String[] args) { //第一个参数是访问时的url,9091是任意一个不占用的端口        Endpoint.publish("http://localhost:9091/S
应用Python开发WebService服务端及客户端
热门推荐
TechRunner
04-24 1万+
使用Python开发WebService,实现服务端、客户端,及完成接口调用。
python3.9.x发布webservice用于数据传输
doll123456662的博客
12-06 4437
WebService主要有三大要素:XML,SOAP和WSDL。采用XML格式封装,并增加了SOAP协议规定的的HTTP消息头,通过一个WSDL文件来说明自己有什么服务可以对外调用。适用于一些复杂数据类型的传输。 python3.9.8 pycharm2021.2.1 服务端:主要用到spyne包,简单明了,直接上代码 import json from spyne import Application, rpc, ServiceBase, Iterable, Integer, Unicode, S.
pythonflask怎么开发web_使用Python-Flask框架开发Web网站系列课程(一)构建项目
最新发布
06-01
好的,关于使用 Python-Flask 框架开发 Web 网站,我可以为您提供一些指导。 首先,您需要安装 Flask 和其他必要的依赖项。您可以使用 pip 命令来安装 Flask: ``` pip install Flask ``` 接下来,您可以创建一个 Flask 应用程序,如下所示: ```python from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, World!' ``` 以上代码创建了一个名为 `app` 的 Flask 应用程序,并定义了一个路由,该路由将 URL `/` 映射到名为 `hello_world()` 的函数。在此示例中,`hello_world()` 函数只返回字符串 `'Hello, World!'`。 您可以使用以下命令运行应用程序: ``` export FLASK_APP=your_app_name flask run ``` 在这个示例中,您需要将 `your_app_name` 替换为您的应用程序名称。此命令将启动 Flask 开发服务器,您可以在浏览器中通过访问 `http://localhost:5000/` 来查看应用程序。 接下来,您可以使用 Flask 和其他 Python 库来构建您的 Web 应用程序。您可以定义更多的路由、使用数据库、使用模板等等。 希望这些信息对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • nmap扫描局域网存活主机_nmap扫描在线主机的几种方法 37441
  • opc ua与opc da区别_OPC,OPCDA,OPCUA傻傻搞不清楚,走过路过不妨看一看 26591
  • html颜色对应卡,PANTONE色卡 10875
  • 怎么设置计算机键盘数字键,电脑右边的数字键不能用怎么办_电脑右边数字键盘用不了的修复方法... 10090
  • mysql double类型长度_Mysql系列 第2天:详解mysql数据类型(重点) 7453

大家在看

  • Python | Leetcode Python题解之第131题分割回文串
  • 「vue」vue + nodejs实现防伪码业务逻辑
  • 【数据结构】穿梭在二叉树的时间隧道:顺序存储的实现 1115
  • Golang | Leetcode Golang题解之第131题分割回文串
  • 一维时间序列突变检测方法(小波等,MATLAB R2021B) 287

最新文章

  • 虚拟机怎么启动共享文件服务器,VMWARE怎么直接执行共享宿主机文件夹上的可执行文件...
  • intel服务器芯片排行,【2021Intel服务器CPU排行榜】Intel服务器CPU哪款好_热门Intel服务器CPU推荐-太平洋产品报价...
  • 连接svn服务器没有响应,svn服务器连接失败解决方法
2021年137篇
2020年213篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

深圳SEO优化公司常德企业网站制作价格烟台网站优化软件报价石家庄模板推广推荐兰州网络广告推广公司呼和浩特设计网站哪家好黄冈网站推广方案报价德州百姓网标王公司芜湖外贸网站建设公司海口外贸网站制作报价海南建网站多少钱新乡外贸网站设计海北网站排名优化价格百搜标王哪家好宿州外贸网站建设漳州网页设计价格和县外贸网站制作价格张北SEO按天扣费多少钱泰州网站制作鸡西网站推广系统价格济宁阿里店铺运营公司泰州建站价格重庆网站搭建多少钱新余seo济南关键词按天扣费公司日照外贸网站建设价格自贡网站改版推荐柳州网站设计模板丽江seo价格肇庆百度关键词包年推广价格乌海模板网站建设哪家好歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化