Scrapy 爬虫入门 +实战

 

从接触MVC到明天早已有七个月了,写点自个儿的心德,好与不佳,希望交给意见,有谈得来原创的也有转发的

 

【转】:http://www.cnblogs.com/zhangziqiu/archive/2009/02/28/aspnet-mvc-2.html

 爬虫,其实很已经有提到到那么些点,不过一贯尚未深切,后天来搞爬虫。选取了,scrapy那几个框架

从零开首学习 ASP.NET MVC 一.0 (2) 识别U福特ExplorerL的Routing组件

 一.摘要

本篇文章从基础到深刻的牵线ASP.NET MVC中的Routing组件.
Routing翻译过来是”路由精选”, 负责ASP.NET MVC的首先个工作:识别U悍马H2L,
将七个Url请求”路由”给Controller.

 

http://scrapy-chs.readthedocs.io/zh\_CN/0.24/intro/tutorial.html
入门教程

二.承上启下

首先篇小说中大家曾经学会了哪些利用ASP.NET MVC,
即使当中还有众多的细节尚未尖锐掌握,
但是对中央的拍卖流程已经有了认识:来了2个Url请求,
从中找到Controller和Action的值, 将请求传递给Controller处理.
Controller获取Model数据对象, 并且将Model传递给View,
最后View负责展现页面.

而Routing的效益正是承担分析Url, 从Url中分辨参数, 如图:

图片 1

那壹讲就让大家密切的垂询System.Web.Routing及其有关的扩充知识.

实际上安装依然非常的粗略的,我们得以一向pip install scrapy

三.Routing的作用

首先讲中实例的首页地址是: localhost/home/index

咱俩发现访问上面的地址, 最后会传递给
HomeController中名字为index的action(即HomeController类中的index方法).

自然服务器端不会融洽去贯彻这几个功用, 
关键点正是在Global.asax.cs文件中的下列代码:

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );

        }

        protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
        }

 

回去看大家的Url: localhost/home/index

localhost是域名, 所以首先要去掉域名部分: home/index

对应了上面代码中的那种U科雷傲L结构: {controller}/{action}/{id}

因为我们创设了那种Url结构的鉴定区别规则, 所以能够分辨出 Controller是home,
action是index, id未有则为私下认可值””.

那正是Routing的首先个职能:

一.从Url中分辨出数据.比如controller,action和种种参数.

假定跟踪程序, 接下来我们会跳转到HomeController中的Index()方法. 
这是Routing内部为落到实处的第一个效益:

二.基于识别出来的数目, 将请求传递给Controller和Action.

但从实例中我们并不知道Routing如何做的那部份工作.第四有的我做了深远讲解.

假使报错也足以去下载https://pypi.python.org/pypi/Scrapy

四.Routing的使用

在解析Routing的达成原理前, 先学习怎么利用Routing为ASP.NET
MVC程序添加路由规则.

Scrapy-1.4.0-py2.py3-none-any.whl
(md5)进行安装,安装报错,要求去下载提醒的库,

1. 使用MapRoute()方法.

那是最简易的为ASP.NET MVC添加识别规则的方法.此方法有如下重载:

MapRoute( string name, string url);
MapRoute( string name, string url, object defaults);
MapRoute( string name, string url, string[] namespaces);
MapRoute( string name, string url, object defaults, object constraints);
MapRoute( string name, string url, object defaults, string[] namespaces);
MapRoute( string name, string url, object defaults, object constraints, string[] namespaces);

 

Twisted安装:

下载http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted

然后安装

name参数:

平整名称, 能够随意起名.当时不得以重名,不然会发生错误:
路由集合中已经存在名称为“Default”的路由。路由名必须是绝无仅有的。

安装PyWin32

从官方网址下载对应版本的安装包即可,链接为:https://sourceforge.net/projects/pywin32/files/pywin32/Build%20221/

下图呈现了Scrapy的大体架构,

图片 2

 

url参数:

url获取数据的平整, 那里不是正则表明式,  将要识其他参数括起来即可, 比如:
{controller}/{action}

起码只需求传递name和url参数就足以创建一条Routing(路由)规则.比如实例中的规则完全能够改为:

            routes.MapRoute(
                    "Default",
                    "{controller}/{action}");

二、组件

1、Scrapy Engine(Scrapy引擎)

Scrapy引擎是用来控制总体种类的数额处理流程,并展开事务处理的接触。愈来愈多的事无巨细内容能够看下边包车型大巴数量处理流程。

2、Scheduler(调度)

调度程序从Scrapy引擎接受请求并排体系入队列,并在Scrapy引擎发出请求后返还给他们。

3、Downloader(下载器)

下载器的首要职责是抓取网页并将网页内容返还给蜘蛛( Spiders)。

4、Spiders(蜘蛛)

蜘蛛是有Scrapy用户自个儿定义用来分析网页并抓取制定U中华VL再次来到的始末的类,每一个蜘蛛都能处理1个域名或1组域名。换句话说正是用来定义特定网址的抓取和剖析规则。

蜘蛛的整个抓取流程(周期)是这么的:

率先得到第一个UPRADOL的开头请求,当呼吁重返后调取二个回调函数。第五个请求是通过调用start_requests()方法。该方法暗中认可从start_urls中的Url中变化请求,并实施解析来调用回调函数。

在回调函数中,你能够分析网页响应并赶回项目对象和请求对象或二者的迭代。那几个请求也将含有3个回调,然后被Scrapy下载,然后有钦命的回调解和处理理。

在回调函数中,你分析网址的情节,同程使用的是Xpath选用器(不过你也足以利用BeautifuSoup,
lxml或任何任何你欣赏的顺序),并扭转解析的多少项。

末尾,从蜘蛛重返的档次一般会进驻到花色管道。

5、Item Pipeline(项目管道)

花色管道的显要权利是承担处理有蜘蛛从网页中抽取的连串,他的第贰职务是清楚、验证和存储数据。当页面被蜘蛛解析后,将被发送到项目管道,并经过多少个特定的先后处理多少。每一个项目管道的零部件都是有二个粗略的措施结合的Python类。他们得到了种类并推行他们的艺术,同时他们还亟需规定的是是还是不是必要在档次管道中继续执行下一步或是直接吐弃掉不处理。

项目管道平时执行的进度有:

清洗HTML数据
注明解析到的数码(检查项目是不是带有须求的字段)
反省是或不是是重复数据(假如重复就删除)
将分析到的数目存款和储蓄到数据库中

陆、Downloader middlewares(下载器中间件)

下载中间件是置身Scrapy引擎和下载器之间的钩子框架,主如若拍卖Scrapy引擎与下载器之间的伸手及响应。它提供了贰个自定义的代码的点子来进展Scrapy的功能。下载中间器是1个甩卖请求和响应的钩子框架。他是轻量级的,对Scrapy尽享全局控制的头部的体系。

七、Spider middlewares(蜘蛛中间件)

蜘蛛中间件是介于Scrapy引擎和蜘蛛之间的钩框架,主要工作是拍卖蜘蛛的响应输入和伸手输出。它提供二个自定义代码的措施来实行Scrapy的成效。蛛中间件是四个挂接到Scrapy的蜘蛛处理体制的框架,你可以插入自定义的代码来处理发送给蜘蛛的呼吁和重返蜘蛛获取的响应内容和类型。

八、Scheduler middlewares(调度中间件)

调度中间件是在于Scrapy引擎和调度之间的中间件,主要工作是处从Scrapy引擎发送到调度的伸手和响应。他提供了1个自定义的代码来进展Scrapy的职能。

大家设置后方可去建立3个工程,作者起名字为做baidu

scrapy startproject baidu

目录结构

scrapy.cfg: 项目的配置文件

tutorial/: 该项目的python模块。之后您将在此加入代码。

tutorial/items.py: 项目中的item文件.

tutorial/pipelines.py: 项目中的pipelines文件.

tutorial/settings.py: 项目的设置文件.

tutorial/spiders/: 放置spider代码的目录.

那么开始一个爬虫

我们去分析下这个网站 https://movie.douban.com/top250


我们可以看到,界面所有的都是在ol的标签下,元素的class也是唯一的, 那么我们可以定位到这里,去找到所有的电影的一个集合
xptach是//ol[@class="grid_view"]/li
那么我们来分析下下面的电影

 

 

我们可以看到 我们想要获取的元素是很简单的,都是好获取的元素,
那么我们来顶一下我们要获取的,我们在item.py来定义
    ranking=scrapy.Field() 
    movie_name=scrapy.Field() #电影名称
    score=scrapy.Field()  #分数
    score_num=scrapy.Field()#评分人数
    daoyan=scrapy.Field()#导演,演员
    bieming=scrapy.Field()
    url=scrapy.Field()#url地址
几乎我们可以看到我们想要的元素都可以得到,
那么我们来组织我们的代码

from baidu.items import BaiduItem
from scrapy import Request
import re
class XiaoHuarSpider(scrapy.Spider):
    name = 'douban_movie_top250'
    start_urls=[
         'https://movie.douban.com/top250']

    def parse(self, response):
        item = BaiduItem()
        movies = response.xpath('//ol[@class="grid_view"]/li')
        for movie in movies:
            item['ranking'] = movie.xpath('.//div[@class="pic"]/em/text()').extract()[0]
            item['movie_name'] = movie.xpath('.//div[@class="hd"]/a/span[1]/text()').extract()[0]
            item['score'] = movie.xpath('.//div[@class="star"]/span[@class="rating_num"]/text()').extract()[0]
            item['score_num'] = movie.xpath('.//div[@class="star"]/span/text()').re('(\d+)人评价')[0]
            item['daoyan']=movie.xpath('.//div[@class="bd"]/p/text()').extract()[0]
            item['bieming']=movie.xpath('.//div[@class="bd"]/p[@class="quote"]/span/text()').extract()[0]
            item['url']=movie.xpath('.//div[@class="hd"]/a/@href').extract()[0]
            yield item

 

我们来在命令行来跑下我们的代码

scrapy crawl douban_movie_top250 –logfile=test.log
-o
douban_movie_top250.json
-t
json

图片 3

小编们能够看到是绝非获取到多少了,唯有log日志

翻阅资料发现有人说着可能是被禁止了,那么我们来修改修改,伪造下
加个headers吧

class XiaoHuarSpider(scrapy.Spider):
    name = 'douban_movie_top250'
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36',}
    def start_requests(self):
        url = 'https://movie.douban.com/top250'
        yield Request(url, headers=self.headers)
    def parse(self, response):
        item = BaiduItem()
        movies = response.xpath('//ol[@class="grid_view"]/li')
        for movie in movies:
            item['ranking'] = movie.xpath('.//div[@class="pic"]/em/text()').extract()[0]
            item['movie_name'] = movie.xpath('.//div[@class="hd"]/a/span[1]/text()').extract()[0]
            item['score'] = movie.xpath('.//div[@class="star"]/span[@class="rating_num"]/text()').extract()[0]
            item['score_num'] = movie.xpath('.//div[@class="star"]/span/text()').re('(\d+)人评价')[0]
            item['daoyan']=movie.xpath('.//div[@class="bd"]/p/text()').extract()
            item['bieming']=movie.xpath('.//div[@class="bd"]/p[@class="quote"]/span/text()').extract()[0]
            item['url']=movie.xpath('.//div[@class="hd"]/a/@href').extract()[0]
            yield item

那正是说大家再来运行下大家的代码

看下我们的douba.csv

图片 4

 

在来探视我们的日记模块:

图片 5

 

 大家的日志也得以健康的打印了,那么大家来探视,我们的数据就像少很多,唯有首先页的,那么大家去分析下大家的页面

图片 6

 

似乎我们明白了什么
那么,我们来改进下我们的代码。
增加下面代码

next_url=response.xpath('//span[@class="next"]/a/@href').extract()
        if next_url:
            next_url='https://movie.douban.com/top250'+next_url[0]
            yield Request(next_url,headers=self.headers)

 那么大家再来爬取下我们的爬虫

图片 7

独自看我们明日的数据文件大小,大家是水到渠成的,那么大家来看下大家之中的内容

图片 8

 

日志文件呈现了成都百货上千在此以前从没爬取到的篇章

图片 9

 

爬虫其实也未尝那么复杂,只要您在途中坚贞不屈了。

 

defaults参数:

url参数的暗许值.假诺三个url唯有controller: localhost/home/

同时大家只建立了一条url获取数据规则: {controller}/{action}

那正是说此时就会为action参数设置defaults参数中规定的暗许值.
defaults参数是Object类型,所以能够传递三个匿名类型来初叶化私下认可值:

new { controller = "Home", action = "Index" }

实例中央银行使的是七个参数的MapRoute方法:

            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );

除此以外我提供vip指引,python自动化,python学习方面,python做测试开发方面,笔者都会提供引导,vip终生有效,现价1500,联系qq:9529433八陆,稍后会更新qq群,喜欢的恋人能够来,本人也是从贰个不懂吗是python到现行反革命能做东西,从1伍的2k到一柒的10k+都是辛酸泪,能够与大家壹同共勉,提供思路,能够让你走的更远,小编也是从白纸一张一步步走来,假如您是新结业的学习者那几个也合乎你,能够给你指点,不过笔者能做的正是带您,可是自身不是培养和磨练班,未有提供就业的机遇,笔者只会在有空子的时候给您推荐,学无边无际,此时或然作者只得教您有的测试,提供职业教导,笔者只怕以后会带给你越多。

constraints参数:

用来界定各种参数的规则或Http请求的类型.constraints属性是2个RouteValueDictionary对象,也等于3个字典表,
不过以此字典表的值能够有三种:

用于定义正则表明式的字符串。正则表明式不区分轻重缓急写。

一个用来落到实处 IRouteConstraint 接口且含有
Match
方法的对象。

经过应用正则表明式能够显明参数格式,比如controller参数只好为3个人数字:

new { controller = @"\d{4}"}

 

因而第IRouteConstraint
接口近日得以界定请求的类型.因为System.Web.Routing中提供了HttpMethodConstraint类,
这一个类完成了IRouteConstraint 接口.
大家得以经过为RouteValueDictionary字典对象添加键为”httpMethod”,
值为3个HttpMethodConstraint对象来为路由规则添加HTTP 谓词的范围,
比如限制一条路由规则只好处理GET请求:

httpMethod =  new HttpMethodConstraint(  "GET", "POST"  )

总体的代码如下:

            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" },  // Parameter defaults
                new { controller = @"\d{4}" , httpMethod = new HttpMethodConstraint( "GET", "POST" ) }
            );

理所当然大家也能够在表面先创建多少个RouteValueDictionary对象在作为MapRoute的参数字传送入,
那只是语法难题.

自家是三个大学专科学生,也是一位努力到明天。

 

 

namespaces参数:

此参数对应Route.DataTokens属性. 官方的分解是:

获取或安装传递到路由处理程序但未用于分明该路由是还是不是相配 U本田CR-VL
格局的自定义值。

本人眼下不驾驭什么样选取. 请大师辅导

二.MapRoute方法实例

下边通超过实际例来采用MapRoute方法.
对于多个网址,为了SEO友好,1个网站的U帕杰罗L层次不要抢先三层:

localhost/{频道}/{具体网页}

个中域名第1层, 频道第二层, 那么最终的网页就只剩余最终一层了.
如若选取默许实例中的”{controller}/{action}/{别的参数}”的款型会潜移默化网站的SEO.

假诺大家的网址组织如下:

图片 10

下边以商旅频道为例, 是自家创制的Routing规则:

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            #region 酒店频道部分
            // hotels/list-beijing-100,200-3
            routes.MapRoute(
                "酒店列表页",
                "hotels/{action}-{city}-{price}-{star}",
                new { controller = "Hotel", action = "list", city = "beijing", price="-1,-1", star="-1" },
                new { city=@"[a-zA-Z]*",price=@"(\d)+\,(\d)+", star="[-1-5]"}
                );

            //hotels/所有匹配
            routes.MapRoute(
                "酒店首页",
                "hotels/{*values}",
                new { controller = "Hotel", action = "default", hotelid = "" }
                );
            #endregion

            //网站首页.
            routes.MapRoute(
                 "网站首页",
                 "{*values}",
                 new { controller = "Home", action = "index"}
                 );  
        }

 

实现的效益:

(一)访问 localhost/hotels/list-beijing-100,200-三会造访酒馆频道的列表页,并传播查询参数

(二)访问 localhost/hotels 下边的其余其余页面地址, 都会跳转到客栈首页.

(3)访问 localhost 上边包车型大巴任哪儿方, 借使未相称上面二条, 则跳转到首页.

简简单单总括:

(1)Routing规则有各样(依照添加是的次第),
借使三个url相称了多少个Routing规则, 则依据第1个非常的Routing规则执行.

(二)由于地方的平整, 要将切实频道的切实可行页面放在最下面, 将频道首页 和
网址首页 放在最下方.

(3) {*values} 表示前边能够使任意的格式.

3.使用Route类

MapRoute方法固然简单, 但是他是精神也是经过创制Route类的实例,
为RouteCollection集合添加成员.

下载最新版本的MSDN-Visual Studio 三千八 SP一, 已经得以找到Route类的表明.

成立一个Route类实例,最要害的是为以下多少个属性赋值:

属性名称 说明 举例
Constraints 获取或设置为 URL 参数指定有效值的表达式的词典。 {controller}/{action}/{id}
DataTokens 获取或设置传递到路由处理程序但未用于确定该路由是否匹配 URL 模式的自定义值。 new RouteValueDictionary { { "format", "short" } }
Defaults 获取或设置要在 URL 不包含所有参数时使用的值。 new { controller = "Home", action = "Index", id = "" }
RouteHandler 获取或设置处理路由请求的对象。 new MvcRouteHandler()
Url 获取或设置路由的 URL 模式。 new { controller = @"[^\.]*" }

那几个属性除了RouteHandler以外,
别的的都对应MapRoute方法的参数.RouteHandler是贯彻了IRouteHandler接口的对象.关于此接口的效能在第5局地Routing深远解析中做讲解.

伍.Routing深刻剖析

对此多个1般开发职员来说, 上边包车型客车知识已经完全丰富你采用ASP.NET
MVC时利用Routing了.

接下去的壹些自身将深刻Routing的机制讲解Routing的尖端应用.可是因为是”高级应用”,
加上那篇文章已经太长了, 再添加马上昨天就过去了,
“每一天一篇”的应允一定要兑现的, 所以不会对负有细节举办讲解.
或然也足以略过此部分.

Routing怎么着将呼吁传递给Controller?上面讲解Routing成效的时候,
大家就分析出Routing会将呼吁传递给Controller,
不过Routing如何做的那部份工作我们却看不到.关键在于MapRoute()这几个方式封装了切实可行的细节.

即使MapRoute方法是RouteCollection对象的法子,但是却被放置在System.Web.Mvc程序集中,
如若你的次序只援引了System.Web.Routing,
那么RouteCollection对象是不会有MapRoute方法的.
不过只要你同又引述了System.Web.Mvc,
则在mvc的dll中为RouteCollection对象添加了扩展方法:

       public static void IgnoreRoute(this RouteCollection routes, string url);
        public static void IgnoreRoute(this RouteCollection routes, string url, object constraints);
        public static Route MapRoute(this RouteCollection routes, string name, string url);
        public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults);
        public static Route MapRoute(this RouteCollection routes, string name, string url, string[] namespaces);
        public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints);
        public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces);
        public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces);

RouteCollection是贰个凑合,他的每1项应该是1个Route对象.
然则大家采用MapRoute时并从未创建这些指标,
这是因为当大家将MapRoute方法必要的参数传入时,
在点子内部会基于参数成立一个Route对象:

        public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) {
            if (routes == null) {
                throw new ArgumentNullException("routes");
            }
            if (url == null) {
                throw new ArgumentNullException("url");
            }

            Route route = new Route(url, new MvcRouteHandler()) {
                Defaults = new RouteValueDictionary(defaults),
                Constraints = new RouteValueDictionary(constraints)
            };

            if ((namespaces != null) && (namespaces.Length > 0)) {
                route.DataTokens = new RouteValueDictionary();
                route.DataTokens["Namespaces"] = namespaces;
            }

            routes.Add(name, route);

            return route;
        }

地方便是MapRoute方法的实现,
至于在创立Route对象时第三个参数是3个MvcRouteHandler,
它是三个贯彻了IRouteHandler接口的类. IRouteHandler十三分不难唯有二个形式:

IHttpHandler GetHttpHandler(RequestContext requestContext);

参数是1个RequestContext 类实例, 那一个类的结构也很简短:

    public class RequestContext
    {
        public RequestContext(HttpContextBase httpContext, RouteData routeData);

        public HttpContextBase HttpContext { get; }
        public RouteData RouteData { get; }
    }

个中的二性情能RouteData就富含了Routing依照Url识别出来各类参数的值,
个中就有Controller和Action的值.

谈到底, ASP.NET MVC最终依旧利用HttpHandler处理请求. ASP.NET
MVC定义了投机的贯彻了IHttpHandler接口的Handler:MvcHandler, 
因为MvcRouteHandler的GetHttpHandler方法最终回来的正是MvcHandler. 

MvcHandler的构造函数须要传入RequestContext 对象,
也正是流传了独具的全体要求的多少,
所以最终能够找到对应的Controller和Action, 已经种种参数.

六.测试Routing

因为2个Url会相配八个routing规则,
最终常常会遭遇规则写错可能顺序不对的难题.于是大家希望能够看出Url相称Routing的结果.

个中最简便易行的办法正是使用RouteDebug帮忙类. 那些类须求独自下载dll组件,
笔者将此组件的下载放在了天涯论坛上:

http://files.cnblogs.com/zhangziqiu/RouteDebug-Binary.zip

解压缩后是二个DLL文件, 将以此DLL文件添加到项目中而且拉长引用.

采纳办法很简短, 只要求在Application_Start方法中添加一句话:

RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);

譬如说上面是本人的言传身教中的代码:

        protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
            RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
        }

昨日您拜访任何UPAJEROL, 都会现出RouteDebug页面, 如下:

图片 11

当中不仅有您的持有Routing规则, 还显示了是不是相配.并且依据顺体系出.
还有识别的参数列表.

当您不想测试Routing规则的时候则注释掉那一段, 即可回复跳转到View对象上.

七.总结

本文讲解了ASP.NET MVC中三个至关心珍视要的零件:Routing的使用.
System.Web.Routing在Framework三.伍 SP第11中学曾经集成,
也正是说固然大家还不曾ASP.NET MVC的正式版,
不过Routing组件却1度提前发布了. 因为Routing是一个相对独立的零件,
不仅能和ASP.NET MVC分配的定额使用, 也足以用于其余须求ULANDL路由的项目.
另外Routing的机能和Url重写(Url Rewrite)是有分其余, 你会发现Routing和Url
Rewrite相比较其实很辛劳,
无论是添加规则依旧传递参数.对UrlRewite感兴趣的能够去寻觅UrlRewrite.dll这么些组件,
很简短很强劲, 有关两岸的异议以及哪些运用UrlRewrite那里不在多说了.

正文的演示下载地址:

http://files.cnblogs.com/zhangziqiu/Demo-2.rar

 

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图