博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python web多sitemap创建更新解决方案
阅读量:4442 次
发布时间:2019-06-07

本文共 20377 字,大约阅读时间需要 67 分钟。

目录

Python web多sitemap创建更新解决方案


这篇博客主要介绍本人对于Python web(这里使用的是Flask)使用多sitemap(即因为网站存在大量平均增长的页面)的解决思路与方案:

  • 两种sitemap自动创建更新解决方案对比
  • 方案详解

两种sitemap自动创建更新解决方案对比

方案一: 使用路由视图和模板语言自动生成

一般来说,使用python进行web开发,最简单的sitemap解决方法就是使用模板语言来创建sitemap.xml文件, 也就是的动态创建sitemap,这种方法的基本思路就是:

搜索引擎每次通过url访问该网站的sitemap文件的时候,通过路由从数据库中查询获取数据,然后填充到sitemap模板并返回.

这样做的好处以下几点:

1.除开网站的基本页面(如首页,登录页)以外,其余由由用户创建的网页(如博客,帖子)的sitemap的更新都不用管理员去手动或这调用任何命令去更新,因为搜索引擎每次访问的时候,就会自动返回从数据库中获取的最新的数据

2.简单方便,只需要写一个路由接口(视图)然后给出一个sitemap模板,就可以了.

这种方法虽然最简单方便,但是缺点也显而易见:

  • 由于单个sitemap文件中包含的url上限不能超过50000个,所以这种方法只适合用户基数以及网站页面不多的小型网站, 因为小型网站一般只有一个sitemap文件。
    所以说这种方法不适用于需要多个sitemap文件的页面较多的网站.

方案二:运用python的xml模块进行sitemap文件的创建与更新

这种方案,也是本人目前这里运用并将要详细介绍的方案。

这种解决方案,基本思路就是写一个集中控制sitemap文件创建和更新的方法,然后可将其作为命令调用,并设置为服务器定时任务对sitemap进行定时更新,或提供后台管理进行调用。
那么很明显,对比上面的方案一,这两种方案的最大区别就在于:

  • 除开网站基本页面的更新(如首页,登陆等)需要人为去修改以外,对于其余的平均增长的页面(如帖子,博客等),这种方案需要管理员或linux定时任务来调用更新sitemap的方法,而上面的方案一,则完全依赖于搜索引擎那边何时访问(更新)本网站的sitemap

这种方案虽然比上面的方案一要复杂很多,但是好处在于:

  1. 适用于用户基数和页面较多的网站,因为这种方法可以管理多个sitemap的创建和更新,这样就解决了单个sitemap中url上限的问题
  2. 由于是纯粹的靠python的xml模块来进行对sitemap文件的创建和更新,也就纯粹的对文件的读写操作,所以对sitemap文件的可控性更强

    比如,一个sitemap文件的内容更新后,需要根据这个sitemap文件更新的内容去更新另一个sitemap文件中的内容。


方案详解

下面将详细讲解方案二的运用实例,这里我们主要使用的是python xml模块中的etree模块

注意:

etree模块对于读取非信任渠道的数据是有安全隐患的,如读取用户和前端传过来的数据,但这里我们用于操作自己网站的sitemap文件,所以这里不计较这个安全性问题。

首先说明一下这里的应用情景:这里我们有一个发帖的网站,我们要在sitemap文件中录入每一篇帖子,并且有新帖子发布的时候,要更新sitemap中帖子广场页面的url。

Sitemap文件列表:

sitemap文件名 作用
sitemap_index.xml sitemap索引文件,索引多个sitemap文件,向搜索引擎提交的就是这个文件
s_posts_(n).xml 帖子页面的sitemap文件,n表示版本号,下面将详细介绍这个版本号的作用
s_base.xml 基本页面的sitemap文件,如首页,登陆页,帖子广场页面等,此sitemap文件大多数时候是需要人为写入和修改的。

每个用途的sitemap文件大体内容结构:

  • sitemap_index.xml
  • s_posts.xml
  • s_base.xml
http://www.xfc.com/posts

此方案更新sitemap文件的大体流程如下:

st=>start: 调用更新所有sitemap的方法e=>end: 写入所有更新的内容到对应的sitemap文件op=>operation: 更新帖子sitemapop2=>operation: 连带更新帖子库的sitemapop3=>operation: 最终更新sitemap索引文件中上面被更新的子sitemap文件的索引st->op->op2->op3->e

接下来进入代码详解的正题:

首先我们创建一个类,一个用于封装sitemap文件的信息和操作的类,这是我们整个方案的核心之一:

from xml.etree import ElementTree as ETimport osfrom flask import url_forimport ModelPostfrom datetime import datetimeSITEMAP_DIR = os.path.join(os.path.abspath(os.path.dirname(__name__)), "xfc/static/sitemaps")SITEMAP_URL = "http://wwww.xfc.cn/static/sitemaps/"INDEX_SITEMAP_NAME = "sitemap_index"POSTS_SITEMAP_NAME = 's_posts'BASE_SITEMAP_NAME = "s_base"lastmod_format = "%Y-%m-%dT%H:%M:%S+00:00"# sitemap更新状态NO_UPDATE = 0MODIFY = 1NEW_UPDATE = 2# 每个sitemap文件最大url数量URL_MAX_COUNT = 50000# 默认模型帖子url数值DEF_POST_PRIORITY = "0.6"DEF_POST_CHANGEFREQ = "Weekly"
class SitemapFile:    """    针对sitemap文件的获取, 创建和写入    """    def __init__(self, base_name, sitemap_dir=SITEMAP_DIR, index=False):        """        获取对应sitemap文件信息并赋值给实例        :param base_name: sitemap文件的基本名称(不包含后缀和版本)        :param sitemap_dir: 放置sitemap文件的目录        :param index: 是否为sitemap索引文件        """        self.sitemap_dir = sitemap_dir        if not os.path.exists(self.sitemap_dir):            os.makedirs(self.sitemap_dir)        # 是否为索引文件        if index:            xml_item = self.get_index(base_name)        else:            xml_item = self.get_child_sitemap(base_name)      # 赋给实例对应sitemap文件的属性值,这样最终得到SitemapFile就封装了对应sitemap文件的属性和操作,方便我们后续的操作        self.base_name = base_name        self.xml_name = xml_item.get("xml_name")        self.xml_path = xml_item.get("xml_path")        self.xml_tree = xml_item.get("xml_tree")        self.index = index        self.update = NO_UPDATE        self.xml_item = xml_item    def get_index(self, base_name="sitemap_index"):    """获取sitemap索引文件"""        pass    def get_child_sitemap(self, base_name, auto_change=False):    """获取普通的sitemap文件(被索引的子sitemap文件)"""        pass            def get_sitemap_item(self, base_name, stmp_version=0):    """获取sitemap文件的信息"""        pass    def write(self):    """将更新的内容写入到对应的sitemap文件"""        pass

首先我们注意 get_child_sitemap和get_sitemap_item这个两个方法:

  • get_child_sitemap就是用于获取被索引的子sitemap文件,也就是获取s_posts.xml和s_base.xml这类的sitemap文件
def get_child_sitemap(self, base_name, auto_change=False):        """        :param auto_change 是否检测对应的sitemap文件的url数量超过上限与否,如果超过上线则获取更高的一个版本的sitemap,直至最终获取到可用的sitemap文件        """        version = 0        # 这里调用该方法获取到对应的sitemap文件信息键值对        xml_item = self.get_sitemap_item(base_name)        if xml_item and auto_change:        # 运用while循环来获取最终可用的sitemap文件            while not check_url_count(xml_item["xml_tree"]):                version += 1                # 通过调用get_sitemap_item来获取对应的sitemap的文件信息建值对                xml_item = self.get_sitemap_item(base_name, stmp_version=version)                if not xml_item:                    break        return xml_item
  • get_sitemap_item
def get_sitemap_item(self, base_name, stmp_version=0):        # 通过base_name加上版本号加上后缀获取到文件名        filename = "_".join([base_name, str(stmp_version)]) + ".xml"        # 这里的sitemap_dir即默认存放sitemap文件的位置        xml_path = os.path.join(self.sitemap_dir, filename)        # 检测sitemap文件是否存在,如果不存在则创建        if not os.path.exists(xml_path):            # 通过字符串创建一个Elememnt对象            xml_str = "
" root = ET.fromstring(xml_str) # 再将这个Element对象转换为一个ElementTree对象 tree = ET.ElementTree(root) try: # 最终通过ElementTree对象将内容写入到指定路径中,这样就创建了一个有内容的xml文件 # 此处的xml_declaration和encoding="utf-8"表示在xml文件内容开头添加一行声明
tree.write(xml_path, xml_declaration=True, encoding="utf-8") except Exception as e: print("获取%s的sitemap文件失败: %s" % (base_name, e)) raise e else: # 通过路径解析指定的xml文件,并返回一个ElementTree对象 tree = ET.parse(xml_path) # 返回sitemap文件名,对应的ElementTree对象(对sitemap文件内容本身的一切操作主要通过这个对象)以及sitemap文件路径 return {"xml_name": filename, "xml_tree": tree, "xml_path": xml_path}

这里需要注意两个概念:

  1. base_name: 表示某个用途的sitemap文件的基础名,如用于录入帖子页面的sitemap文件的基础名就是 s_posts
  2. version或stmp_version: 这个参数表示版本号。上面说过我们的这个解决方案主要为适用于对多个sitemap文件进行创建更新,如录入帖子页面的sitemap文件,当第一个文件: s_posts_0.xml (s_posts是基础名, 0是版本号)中的url达到上限,也就是录入的帖子页面超过50000了(50000为规定的最大上限),那么我们将会将剩余和以后的帖子页面写入到更高一个版本的sitemap文件中: s_posts_1.xml,以此类推,这就保证了我们帖子页面都能有效地进行sitemap的录入

那么获取sitemap索引文件也大致相同,只不过不需要考虑版本号的问题,因为要是索引文件超出最大限制显然是不和常理的:

def get_index(self, base_name="sitemap_index"):        """        获取sitemap索引文件        :return 返回sitemap文件信息建值对        """        filename = base_name + ".xml"        index_file = os.path.join(self.sitemap_dir, filename)        try:            tree = ET.parse(index_file)        except Exception as e:            print("获取sitemap索引文件失败: %s" % e)            raise e        else:            return {"xml_tree": tree, "xml_path": index_file, "xml_name": filename}

好的,那么接下将就是我们这里至关重要的一步,那就是将更新和修改的内容写入到对应的sitemap文件中:

def write(self):        """        这个方法会将修改后的sitemap内容通过对应的ElementTree对象写入到对应的sitemap文件中,但在这之前会对内容进行检测和迁移到合适版本的sitemap文件中        """        # 先装入当前版本号的sitemap文件名        update_stmp = [self.xml_name]        # 通过check_url_count方法检测当前实例对应的sitemap文件中的url是否超过最大上限        over_max = not check_url_count(self.xml_tree)        # 没有超过最大数量的情况下直接写入当前修改内容到对应的sitemap文件        if not over_max:            try:                self.xml_tree.write(self.xml_path, xml_declaration=True, encoding="utf-8")            except Exception as e:                print("写入文件失败: %s" % e)                raise e            else:                # 返回被更新的sitemap文件名列表                return update_stmp        # 超出最大数量的情况下,我们就要将超出的url从当前版本的sitemap文件迁移到更高一个版本的sitemap文件,这也是整个多sitemap文件管理的核心动作        # 运用while循环以此类推        # 首先从第一个版本开始        version = 0        old_tree = self.xml_tree        while over_max:            version += 1            # 首先获取sitemap文件中所有的url节点对象,也就是已被录入的所有页面            # 获取到超出最大上限数量的url节点对象            urls = old_tree.findall("url")            over_urls = urls[URL_MAX_COUNT:]            if not over_urls:                break            # 然后我们通过字符串创建一个新的ElementTree对象            new_tree = ET.ElementTree(ET.fromstring("
")) urlset = new_tree.getroot() for url in over_urls: # 这里要将当前版本的sitemap文件中超出的url节点移动到更高一个版本的sitemap文件中 # 这里的ET.SubElement创建了一个urlset的子元素对象 # 通过clone_url方法将超出的url节点信息克隆到新的url中 # 这里不能直接将超出的url直接设置为更高版本的sitemap文件的url,否则会报错 # 所以只能通过复制信息的方式来达到移动的目的 clone_url(ET.SubElement(urlset, "url"), url) try: # 再将超出的url节点从已超出容量的sitemap文件(也就是当前版本的sitemap文件)中移除 # 这样就完成了迁移url节点这个动作 old_tree.getroot().remove(url) except: continue # 最后获取当前版本的文明和路径 # 为什么这里不直接调用self.xml_name和self.xml_path呢,因为我们这里要根据当前版本动态获取文件名和路径 old_tree_fn = "_".join([self.base_name, str(version-1)]) + ".xml" old_tree_path = os.path.join(self.sitemap_dir, old_tree_fn) tree_fn = "_".join([self.base_name, str(version)]) + ".xml" tree_path = os.path.join(self.sitemap_dir, tree_fn) try: # 最终将当前版本和更高一个版本的sitemap文件的修改内容分别写入到对应的sitemap文件中 old_tree.write(old_tree_path, xml_declaration=True, encoding="utf-8") new_tree.write(tree_path, xml_declaration=True, encoding="utf-8") except Exception as e: print("写入sitemap文件失败") raise e # 将被修改的sitemap文件名装入这个数组中 update_stmp.append(tree_fn) # 再次检测新写入的sitemap文件是否还是也超过了最大上限,并准备下一次循环 old_tree = new_tree over_max = not check_url_count(old_tree) # 返回被更新的sitemap文件名列表 return update_stmp

这个方法至关重要,是整个sitemap文件解决方案的核心动作,主要运用值交换和循环检测的手段来达到保证每个sitemap中的url不超过上限。

我们先不会管哪些sitemap文件可用,哪些sitemap文件已超出上限,而是将所有的修改和更新操作都建立在第一个版本的sitemap文件对应的ElementTree对象上,然后在最后将要内容写入到文件中时,来进行内容的检测和迁移。

为避免读者对sitemap文件本身和SitemapFile对象和ElementTree对象之间关系的理解混乱,这里给出三者的关系:

st=>start: sitemap文件e=>end: SitemapFile对象op=>operation: 解析xml文件得到ElementTree对象op2=>operation: 封装对ElementTree对象的操作st->op->op2->e

这里给出上面调用的check_url_count和clone_url方法:

def check_url_count(xml, max_count=URL_MAX_COUNT):    """    检测sitemap中url的数量是否超过上限数量(50000)    :param max_count: 单个sitemap的url最大数量    :param xml:    :return Boolean: 该sitemap文件是否还可以填入新的url    """    if isinstance(xml, ET.ElementTree):        tree = xml    else:        tree = ET.parse(xml)    root = tree.getroot()    url_doms = root.findall("url")    if len(url_doms) >= max_count:        return False    return Truedef clone_url(new_url, old_url):    """    克隆url中的元素数据为一个新的url    :param new_url:    :param old_url: 被克隆的url    :return: new_url    """    for child in old_url:        new_child = ET.SubElement(new_url, child.tag)        new_child.text = child.text    return new_url

 接下来我们将介绍帖子页面和帖子广场页面的sitemap具体更新操作:

def update_post_sitemap(stmp_file):    """    集中检测模型帖子的sitemap的更新, 并进相应操作    :params stmp_file: SitemapFile对象,封装了帖子页面的sitemap文件的属性和操作    """    cur_tree = stmp_file.xml_tree    # 获取sitemap文件中所有的url节点元素    url_doms = cur_tree.iter("url")    update = stmp_file.update    post_items = []    post_ids = []    # 解析出sitemap 
元素中的post id for url_dom in url_doms: # 获取url节点元素中的loc子元素的值,也就是帖子页面的url loc_dom = url_dom.find("loc") url_items = loc_dom.text.split("/") # 在url中,我们拆分出帖子的id post_id = url_items[len(url_items) - 2] # 将每个已录入到sitemap中的帖子的id和对应的url节点元素装入post_item中 post_item = {"post_id": post_id, "url_dom": url_dom} post_items.append(post_item) # 单独装入每个帖子的id post_ids.append(post_id) # 查询出没有记录到sitemap的post unsmp_posts = ModelPost.query.filter(ModelPost.id.notin_(post_ids)).all() print("已录入的模型帖子页面的数量: %s" % len(post_items)) print("需要录入的模型帖子页面的数量: %s" % len(unsmp_posts)) update_count = 0 delete_count = 0 # 检测已记录的post是否需要更新sitemap,有则更新sitemap if post_items: for post_item in post_items: # 获取每个url节点中的lastmod子节点的值,也就是已录入到sitemap中的帖子的最后一次修改时间 insmp_lastmod = post_item["url_dom"].find("lastmod").text post = ModelPost.query.filter_by(id=post_item["post_id"]).first() if post: # 这里我们对比数据库中的帖子的最后一次修改时间和已录入到sitemap中的帖子的url的lastmod if post.edit_time.strftime(lastmod_format) != insmp_lastmod: # 如果数据库中的帖子修改时间已更新,那么我们就要更新sitemap中的lastmod # 通过调用udpate_post_url来修改对应post的url节点元素 cur_tree = update_post_url(post, cur_tree, modify=True) # 这里记录被操作的sitemap文件的更新的状态 if not update: update = MODIFY update_count += 1 else: # 数据库中没有查询到该帖子,那么则说明该帖子已被删除,则我们要将这条无效的帖子页面从sitemap中移除 cur_tree = delete_url_dom(cur_tree, post_item["url_dom"].find("loc").text) if not update: update = MODIFY delete_count += 1 print("需要更新的模型帖子页面数量: %s" % update_count) print("需要删除的模型帖子页面数量: %s" % delete_count) # 将未记录到sitemap的帖子录入到sitemap中 if unsmp_posts: for post in unsmp_posts: # 通过调用udpate_post_url来新增url到sitemap中 cur_tree = update_post_url(post, cur_tree) # 由于这里是添加新的url,所以这里更新udpate状态为NEW_UPDATE if update <= MODIFY: update = NEW_UPDATE # 这里我们更新SitemapFile对象中的xml_tree(ElementTree实例) stmp_file.xml_tree = cur_tree stmp_file.update = update return stmp_file

这里最需要说明的一点就是关于ElementTree元素:

尽量保证一个sitemap文件只被一个ElementTree对象操作,因为通过同一个sitemap文件解析出来的ElementTree对象在调用write方法写入修改的内容到sitemap文件中时,最后一个调用write方法的ElementTree对象会覆盖掉前面调用write方法的ElementTree对象的写入的内容。所以这里我们将所有的内容的修改都最终传入到一个ElementTree对象上,并最后只让这个ElementTree对象调用write方法

下面给出上面所调用的update_post_url方法(这里不再详细讲解步骤或以后更新):

def update_post_url(post, xml, dom_dict=dict(), modify=False):    """    对sitemap中单个帖子的url的更新操作    :param xml: 文件路径或ElementTree实例    :param dom_dict: url中的元素名称和值    :param modify: 修改url or 添加url    :return tree: 返回ElementTree    """    dom_dict.setdefault("priority", DEF_POST_PRIORITY)    dom_dict.setdefault("changefreq", DEF_POST_CHANGEFREQ)    dom_dict["lastmod"] = post.edit_time.strftime("%Y-%m-%dT%H:%M:%S+00:00")    post_url = url_for("forum.post_page", post_id=post.id, _external=True)    dom_dict["loc"] = post_url    if modify:        tree = modify_url_dom(xml, dom_dict)    else:        tree = insert_url_dom(xml, dom_dict)    return treedef update_product_url(product_id, dom_dict):    passdef insert_url_dom(xml, dom_dict):    """    添加url到制定的sitemap中    :param dom_dict: 需要添加的元素的名称和值    :param xml: ElementTree实例或者xml文件路径    :return tree: 返回被更新的ElementTree实例    """    if isinstance(xml, ET.ElementTree):        tree = xml    else:        tree = ET.parse(xml)    root = tree.getroot()    url_dom = ET.SubElement(root, "url")    for dom_name in dom_dict.keys():        the_dom = ET.SubElement(url_dom, dom_name)        the_dom.text = dom_dict.get(dom_name)    return treedef modify_url_dom(xml, dom_dict):    """    修改sitemap中指定的url    :param dom_dict: 需要更新的元素的名称和值    :param xml: ElementTree实例或者xml文件路径    :return tree: 返回一个ElementTree实例    """    # 查找要更新的url, 并更新url中的元素的值    if isinstance(xml, ET.ElementTree):        tree = xml    else:        tree = ET.parse(xml)    root = tree.getroot()    url_doms = root.iter("url")    # 一般不修改loc    loc_text = dom_dict.pop("loc")    for url_dom in url_doms:        if url_dom.find("loc").text == loc_text:            for dom_name in dom_dict.keys():                the_dom = url_dom.find(dom_name)                if the_dom is not None:                    if the_dom.text != dom_dict.get(dom_name):                        the_dom.text = dom_dict.get(dom_name)                else:                    the_dom = ET.SubElement(url_dom, dom_name)                    the_dom.text = dom_dict.get(dom_name)        # 顺便填充lastmod        lastmod_dom = url_dom.find("lastmod")        if not lastmod_dom.text:            lastmod_dom.text = datetime.utcnow().strftime(lastmod_format)    return treedef delete_url_dom(xml, loc_text):    """    删除掉sitemap中指定的url    :param loc_text: 通过loc查找到要删除的url    :param xml: ElementTree实例或者xml文件路径    :return tree: 返回被更新的ElementTree实例    """    if isinstance(xml, ET.ElementTree):        tree = xml    else:        tree = ET.parse(xml)    root = tree.getroot()    url_doms = root.iter("url")    for url_dom in url_doms:        if url_dom.find("loc").text == loc_text:            root.remove(url_dom)    return tree

对于上面的python.xml.etree模块的操作的困惑,请查阅官方文档或百度

接下来就是最后的一步也是最开始的一步

集中更新网站所有的sitemap

def update_sitemap():    """    集中更新网站所有sitemap    :return Boolean: 更新成功与否    """    # 这个数组会装入已更新的ElementTree对象,以便将这些ElementTree对象的写入放在最后一起执行    update_smtps = []    # 通过基础名实例化获取封装了对应的sitemap文件操作的SitemapFile对象    s_posts = SitemapFile(POSTS_SITEMAP_NAME)    s_base = SitemapFile(BASE_SITEMAP_NAME)    s_index = SitemapFile(INDEX_SITEMAP_NAME, index=True)    try:        # 对帖子进行sitemap检测并更新操作        s_posts = update_post_sitemap(s_posts)        update_smtps.append(s_posts)        # 模型帖子的sitemap更新,意味着帖子库页面也要更新        if s_posts.update >= NEW_UPDATE:            # 通过调用udpat_models_sitemap方法来更新s_base.xml中的帖子库页面的url节点元素            s_base = update_models_sitemap(s_base)            update_smtps.append(s_base)        # 将所有已ElementTree实例写入到对应的sitemap文件中        write_count = 0        updated_stmps = []        # 这里我们遍历出每个更新过的ElementTree对象        for update_stmp in update_smtps:            # 根据update属性的值判断ElementTree的更新状态            if update_stmp.update >= MODIFY:                # 将每个子sitemap的更新, 写入到对应的子sitemap.xml                # 这里返回被更新的sitemap的文件名                updated_stmps = update_stmp.write()            # 更新sitemap索引文件            if updated_stmps:                write_count += len(updated_stmp)                # 通过调用udpate_index_sitemap方法并传入被更新的siteamp的文件名来更新sitemap索引文件中对应的子sitemap文件(这里主要是更新lastmod的值)                for xml_name in updated_stmps:                    s_index = update_index_sitemap(s_index, child_xml_name=xml_name)        # 写入sitemap索引文件        if s_index.update >= MODIFY:            s_index.write()            write_count += 1            print("更新了sitemap索引文件")    # 反馈更新sitemap的情况信息    except Exception as e:        print("更新sitemap失败: %s" % e)        print("未对sitemap任何进行修改")        return False    else:        if write_count > 0:            print("已成功更新并写入到%s个sitemap文件" % write_count)        else:            print("无需任何更新修改")        return True

给出上面调用的更新sitemap索引文件和更新帖子广场页面的sitemap的方法:

def update_index_sitemap(stmp_file, child_xml_name):    """    更新sitemap索引文件(子sitemap文件修改后,需要更新索引sitemap)    :param child_xml_name: 子sitemap的文件名    :param stmp_file: SitemapFile实例    """    cur_tree = stmp_file.xml_tree    root = cur_tree.getroot()    s_doms = root.findall("sitemap")    update = NO_UPDATE    for s_dom in s_doms:    # 通过每个sitemap节点元素中的loc子节点元素的值来对比child_xml_name(子sitemap的文件名)的值查找需要更新的sitemap元素节点        loc_items = s_dom.find("loc").text.split("/")        if loc_items[len(loc_items) - 1] == child_xml_name:            # 修改lastmod为当前时间            s_dom.find("lastmod").text = datetime.utcnow().strftime(lastmod_format)            update = MODIFY    # 如果当前sitemap索引文件中没有改子sitemap的索引, 则创建    if update <= NO_UPDATE:        s_dom = ET.SubElement(root, "sitemap")        loc = ET.SubElement(s_dom, "loc")        lastmod = ET.SubElement(s_dom, "lastmod")        loc.text = os.path.join(SITEMAP_URL, child_xml_name)        lastmod.text = datetime.utcnow().strftime(lastmod_format)        update = NEW_UPDATE    stmp_file.update = update    stmp_file.xml_tree = cur_tree    return stmp_filedef update_models_sitemap(stmp_file):    """    更新帖子广场页面和搜索页面(新增帖子之后,需要更新帖子广场页面和搜索页面)    这里的搜索页面的内容跟帖子广场页面基本相同    """    cur_tree = stmp_file.xml_tree    lastmod = datetime.utcnow().strftime(lastmod_format)    models_dom = {"loc": "http://www.xfc.com/model", "lastmod": lastmod}    search_dom = {"loc": "http://www.xfc.com/search", "lastmod": lastmod}    # modify_url_dom方法上面已给出    cur_tree = modify_url_dom(cur_tree, models_dom)    cur_tree = modify_url_dom(cur_tree, search_dom)    stmp_file.xml_tree = cur_tree    stmp_file.update = MODIFY    return stmp_file

这两个方法都比较简单,无非就是操作ElemenTree对象来进行修改和更新。


总结

上面已经给出整个方案的全部代码,大多数逻辑上的讲解都在上面代码的注释当中,目前整个方案还有不少的优化和调整的空间,目前的话,读者就当参考参考了。

目录

转载于:https://www.cnblogs.com/xfgrass/p/5793443.html

你可能感兴趣的文章
C++primer 10.2.1节练习
查看>>
perl 执行mysql select 返回多条记录
查看>>
mojo 关闭utf8
查看>>
tomcat架构分析(valve机制)
查看>>
消息队列RabbitMQ基础知识详解
查看>>
接口、抽象类、方法复写、类Equals方法重写
查看>>
快学Scala习题解答—第十章 特质
查看>>
Ffmpeg 定位文件(seek file)
查看>>
数据结构与算法随学随记
查看>>
微软Azure已开始支持hadoop--大数据云计算
查看>>
统计_statistics_不同的人_大样本_分析_统计方法_useful ?
查看>>
wampserver 绑定域名 外部可以正常访问
查看>>
将博客搬至CSDN
查看>>
sqoop/1.4.6/下载
查看>>
https协议及与http协议的比较
查看>>
mongodb数据备份与恢复
查看>>
ubuntu安装(owncloud-docker安装)
查看>>
(十一)tina | openwrt关闭调试串口(DEBUG UART)
查看>>
Android中获取TextView行数
查看>>
AngularJS 学习笔记值post传值
查看>>