手把手实现AI诗歌生成(AI写诗)

本模型采用的是字符级别的诗歌生成(pytorch)环境:python3.Xpytorch GPU或CPU版本都行,另外天有点冷,建议用GPU训练,电脑绝对比暖手宝好用目录项目文件结构:数据已经打包:1、数据集处理2、构建模型与训练模型基于概率语言模型的模型网络结构网络输入输出损失函数3、生成诗歌4、配置文件5、生成效果6、结语参考:项目文件结构:data:存放预处理好的数据model:存放训练好的模型co

本模型采用的是字符级别的诗歌生成(pytorch)

环境:

python3.X

pytorch GPU或CPU版本都行,

另外天有点冷,建议用GPU训练,电脑绝对比暖手宝好用

目录

项目文件结构:

数据已经打包:

1、数据集处理

2、构建模型与训练模型

基于概率语言模型的模型

网络结构

网络输入输出

损失函数

3、生成诗歌

4、配置文件

5、生成效果

6、结语

参考:

目录

项目文件结构:

手把手实现AI诗歌生成(AI写诗)

data:存放预处理好的数据

model:存放训练好的模型

config.py:配置文件

dataHandler.py:数据预处理及生成词典

model.py:模型文件

train.py:训练模型

generation.py:生成诗歌

poetry.txt:全唐诗,四万多首,中华民族艺术瑰宝。

数据已经打包:

链接:https://pan.baidu.com/s/1UAJFf3kKERm_XR0qRNneig 
提取码:e3y5

1、数据集处理

以四万首唐诗的文本作为训练集

它长这样:

手把手实现AI诗歌生成(AI写诗)

文本中每行是一首诗,且使用冒号分割,前面是标题,后面是正文,且诗的长度不一。

对数据的处理流程大致:

  1. 读取文本,按行切分,构成古诗列表。
  2. 将全角、半角的冒号统一替换成半角的。
  3. 按冒号切分诗的标题和内容,只保留诗的内容。
  4. 最后根据诗的内容构建词典,并将处理好的数据保

 处理后的诗歌大概长这样

手把手实现AI诗歌生成(AI写诗)

 代码如下:

# dataHandler.py
import numpy as np
from config import Config


def pad_sequences(sequences,
                  maxlen=None,
                  dtype='int32',
                  padding='pre',
                  truncating='pre',
                  value=0.):
    """
    # 填充
    code from keras
    Pads each sequence to the same length (length of the longest sequence).
    If maxlen is provided, any sequence longer
    than maxlen is truncated to maxlen.
    Truncation happens off either the beginning (default) or
    the end of the sequence.
    Supports post-padding and pre-padding (default).
    Arguments:
        sequences: list of lists where each element is a sequence
        maxlen: int, maximum length
        dtype: type to cast the resulting sequence.
        padding: 'pre' or 'post', pad either before or after each sequence.
        truncating: 'pre' or 'post', remove values from sequences larger than
            maxlen either in the beginning or in the end of the sequence
        value: float, value to pad the sequences to the desired value.
    Returns:
        x: numpy array with dimensions (number_of_sequences, maxlen)
    Raises:
        ValueError: in case of invalid values for `truncating` or `padding`,
            or in case of invalid shape for a `sequences` entry.
    """
    if not hasattr(sequences, '__len__'):
        raise ValueError('`sequences` must be iterable.')
    lengths = []
    for x in sequences:
        if not hasattr(x, '__len__'):
            raise ValueError('`sequences` must be a list of iterables. '
                             'Found non-iterable: ' + str(x))
        lengths.append(len(x))

    num_samples = len(sequences)
    if maxlen is None:
        maxlen = np.max(lengths)

    # take the sample shape from the first non empty sequence
    # checking for consistency in the main loop below.
    sample_shape = tuple()
    for s in sequences:
        if len(s) > 0:  # pylint: disable=g-explicit-length-test
            sample_shape = np.asarray(s).shape[1:]
            break

    x = (np.ones((num_samples, maxlen) + sample_shape) * value).astype(dtype)
    for idx, s in enumerate(sequences):
        if not len(s):  # pylint: disable=g-explicit-length-test
            continue  # empty list/array was found
        if truncating == 'pre':
            trunc = s[-maxlen:]  # pylint: disable=invalid-unary-operand-type
        elif truncating == 'post':
            trunc = s[:maxlen]
        else:
            raise ValueError('Truncating type "%s" not understood' % truncating)

        # check `trunc` has expected shape
        trunc = np.asarray(trunc, dtype=dtype)
        if trunc.shape[1:] != sample_shape:
            raise ValueError(
                'Shape of sample %s of sequence at position %s is different from '
                'expected shape %s'
                % (trunc.shape[1:], idx, sample_shape))

        if padding == 'post':
            x[idx, :len(trunc)] = trunc
        elif padding == 'pre':
            x[idx, -len(trunc):] = trunc
        else:
            raise ValueError('Padding type "%s" not understood' % padding)
    return x

def load_poetry(poetry_file, max_gen_len):
    # 加载数据集
    with open(poetry_file, 'r', encoding='utf-8') as f:
        lines = f.readlines()
        # 将冒号统一成相同格式
        lines = [line.replace(':', ':') for line in lines]
    # 数据集列表
    poetry = []
    # 逐行处理读取到的数据
    for line in lines:
        # 有且只能有一个冒号用来分割标题
        if line.count(':') != 1:
            continue
        # 后半部分不能包含禁止词,如果包含,直接跳过这一首诗
        _, last_part = line.split(':')
        if '(' in line:
            last_part = last_part.split('(')[0]
        # 长度不能超过最大长度
        if len(last_part) > max_gen_len - 2:
            continue
        # 去除这些有禁用词的诗
        if '【' in line or '_' in line:
            continue
        poetry.append(last_part.replace('\n', ''))
    # 随机打乱顺序
    np.random.shuffle(poetry)
    return poetry

def get_data(config):
    # 1.获取数据
    data = load_poetry(config.poetry_file, config.max_gen_len)
    for poetry in data:
        print(poetry)
    # 2.构建词典
    chars = {c for line in data for c in line}
    char_to_ix = {char: ix for ix, char in enumerate(chars)}
    char_to_ix['<EOP>'] = len(char_to_ix)
    char_to_ix['<START>'] = len(char_to_ix)
    char_to_ix['</s>'] = len(char_to_ix)

    ix_to_chars = {ix: char for char, ix in list(char_to_ix.items())}

    # 3.处理样本
    # 3.1 每首诗加上首位符号
    for i in range(0, len(data)):
        data[i] = ['<START>'] + list(data[i]) + ['<EOP>']

    # 3.2 文字转id
    data_id = [[char_to_ix[w] for w in line] for line in data]

    # 3.3 补全既定长度,即填充
    pad_data = pad_sequences(data_id,
                             maxlen=config.poetry_max_len,
                             padding='pre',
                             truncating='post',
                             value=len(char_to_ix) - 1)

    # 3.4 保存处理好的数据
    np.savez_compressed(config.processed_data_path,
                        data=pad_data,
                        word2ix=char_to_ix,
                        ix2word=ix_to_chars)

    return pad_data, char_to_ix, ix_to_chars


if __name__ == '__main__':
    config = Config()
    pad_data, char_to_ix, ix_to_chars = get_data(config)
    for l in pad_data[:10]:
        print(l)

    n = 0
    for k, v in char_to_ix.items():
        print(k, v)
        if n > 10:
            break
        n += 1

    n = 0
    for k, v in ix_to_chars.items():
        print(k, v)
        if n > 10:
            break
        n += 1





2、构建模型与训练模型

基于概率语言模型的模型

我们是基于n-gram语言模型的思想,n-gram模型作了一个n−1阶的Markov假设,即认为一个词出现的概率只与它前面的n−1个词相关,所以我们可以通过前n个词预测下一个词,公式表示为:

手把手实现AI诗歌生成(AI写诗)

STM可以考虑序列之间的联系,所以我们选择LSTM作为本次练习的网络。LSTM详细原理请参考: (31条消息) LSTM这一篇就够了_yingqubaifumei的博客-CSDN博客_lstm细胞状态手把手实现AI诗歌生成(AI写诗)https://blog.csdn.net/yingqubaifumei/article/details/100888147?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164289666916780357223324%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164289666916780357223324&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-100888147.first_rank_v2_pc_rank_v29&utm_term=LSTM&spm=1018.2226.3001.4187

网络结构

基于语言的概率模型本质就是分类模型,基于前面n个字对下一个字进行预测,找到概率最大的字便是预测结果。其网络结构如下:

 手把手实现AI诗歌生成(AI写诗)

 从图中可以看出,本模型使用了1层词嵌入层,2层LSTM,一层全连接层。

网络输入输出

训练数据 x和标签 y,将诗的内容错开一位分别作为数据和标签,举个例子,假设有诗是“床前明月光,疑是地上霜。举头望明月,低头思故乡。”,则数据为“床前明月光,疑是地上霜。举头望明月,低头思故乡。”,标签为“床前明月光,疑是地上霜。举头望明月,低头思故乡。”,两者一一对应,y 是 x 中每个位置的下一个字符。

以字符的形式举例是为了方便理解,实际上不论是x还是y,都是将字符编码后的编号序列(数字),这样才能输入神经网络。

损失函数

损失函数采用交叉熵损失函数CrossEntropyLoss

代码如下:

# model.py
import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.nn.functional as F


class PoetryModel(nn.Module):
    def __init__(self, vocab_size, embedding_dim, hidden_dim, device, layer_num):
        super(PoetryModel, self).__init__()
        self.hidden_dim = hidden_dim

        # 创建embedding层
        self.embeddings = nn.Embedding(vocab_size, embedding_dim)
        # 创建lstm层,参数是输入输出的维度
        self.lstm = nn.LSTM(embedding_dim, self.hidden_dim, num_layers=layer_num)
        # 创建一个线性层
        self.linear1 = nn.Linear(self.hidden_dim, vocab_size)
        # 创建一个dropout层,训练时作用在线性层防止过拟合
        self.dropout = nn.Dropout(0.2)

        self.device = device

    def forward(self, inputs, hidden):
        seq_len, batch_size = inputs.size()
        # 将one-hot形式的input在嵌入矩阵中转换成嵌入向量,torch.Size([length, batch_size, embedding_size])
        embeds = self.embeddings(inputs)

        # 经过lstm层,该层有2个输入,当前x和t=0时的(c,a),
        # output:torch.Size([length, batch_size, hidden_idm]), 每一个step的输出
        # hidden: tuple(torch.Size([layer_num, 32, 256]) torch.Size([1, 32, 256])) # 最后一层输出的ct 和 ht, 在这里是没有用的
        output, hidden = self.lstm(embeds, hidden)

        # 经过线性层,relu激活层 先转换成(max_len*batch_size, 256)维度,再过线性层(length, vocab_size)
        # output = F.relu(self.linear1(output.view(seq_len*batch_size, -1)))
        output = F.log_softmax(self.linear1(output.view(seq_len * batch_size, -1)), dim=1)

        # 输出最终结果,与hidden结果
        return output, hidden

    def init_hidden(self, layer_num, batch_size):
        return (Variable(torch.zeros(layer_num, batch_size, self.hidden_dim)).cuda(),
                Variable(torch.zeros(layer_num, batch_size, self.hidden_dim)).cuda())
# train.py
import os
import torch
import torch.utils.data as Data
import torch.nn as nn
import torch.optim as optim
from model import PoetryModel
from dataHandler import *
from config import Config

class TrainModel(object):
    def __init__(self):

        os.environ["CUDA_VISIBLE_DEVICES"] = '0'
        self.config = Config()
        self.device = torch.device('cuda') if self.config.use_gpu else torch.device('cpu')

    def train(self, data_loader, model, optimizer, criterion, char_to_ix, ix_to_chars):
        for epoch in range(self.config.epoch_num):
            for step, x in enumerate(data_loader):
                # 1.处理数据
                # x: (batch_size,max_len) ==> (max_len, batch_size)
                x = x.long().transpose(1, 0).contiguous()
                x = x.to(self.device)
                optimizer.zero_grad()
                # input,target:  (max_len, batch_size-1)
                input_, target = x[:-1, :], x[1:, :]
                target = target.view(-1)
                # 初始化hidden为(c0, h0): ((layer_num, batch_size, hidden_dim),(layer_num, batch_size, hidden_dim))
                hidden = model.init_hidden(self.config.layer_num, x.size()[1])

                # 2.前向计算
                # print(input.size(), hidden[0].size(), target.size())
                output, _ = model(input_, hidden)
                loss = criterion(output, target) # output:(max_len*batch_size,vocab_size), target:(max_len*batch_size)

                # 反向计算梯度
                loss.backward()

                # 权重更新
                optimizer.step()

                if step == 0:
                    print('epoch: %d,loss: %f' % (epoch, loss.data))

            if epoch % 5 == 0:
                # 保存模型
                torch.save(model.state_dict(), '%s_%s.pth' % (self.config.model_prefix, epoch))

                # 分别以这几个字作为诗歌的第一个字,生成一首藏头诗,用于看看训练时的效果
                word = '春江花月夜凉如水'
                gen_poetry = ''.join(self.generate_head_test(model, word, char_to_ix, ix_to_chars))
                print(gen_poetry)



    def run(self):
        # 1 获取数据
        data, char_to_ix, ix_to_chars = get_data(self.config)
        vocab_size = len(char_to_ix)
        print('样本数:%d' % len(data))
        print('词典大小: %d' % vocab_size)

        # 2 设置dataloader
        data = torch.from_numpy(data)
        data_loader = Data.DataLoader(data,
                                      batch_size=self.config.batch_size,
                                      shuffle=True,
                                      num_workers=0)

        # 3 创建模型
        model = PoetryModel(vocab_size=vocab_size,
                            embedding_dim=self.config.embedding_dim,
                            hidden_dim=self.config.hidden_dim,
                            device=self.device,
                            layer_num=self.config.layer_num)
        model.to(self.device)

        # 4 创建优化器
        optimizer = optim.Adam(model.parameters(), lr=self.config.lr, weight_decay=self.config.weight_decay)

        # 5 创建损失函数,使用与logsoftmax的输出
        criterion = nn.CrossEntropyLoss()

        # 6.训练
        self.train(data_loader, model, optimizer, criterion, char_to_ix, ix_to_chars)

    def generate_head_test(self, model, head_sentence, word_to_ix, ix_to_word):
        """生成藏头诗"""
        poetry = []
        head_char_len = len(head_sentence)  # 要生成的句子的数量
        sentence_len = 0  # 当前句子的数量
        pre_char = '<START>'  # 前一个已经生成的字

        # 准备第一步要输入的数据
        input = (torch.Tensor([word_to_ix['<START>']]).view(1, 1).long()).to(self.device)
        hidden = model.init_hidden(self.config.layer_num, 1)

        for i in range(self.config.max_gen_len):
            # 前向计算出概率最大的当前词
            output, hidden = model(input, hidden)
            top_index = output.data[0].topk(1)[1][0].item()
            char = ix_to_word[top_index]

            # 句首的字用藏头字代替
            if pre_char in ['。', '!', '<START>']:
                if sentence_len == head_char_len:
                    break
                else:
                    char = head_sentence[sentence_len]
                    sentence_len += 1
                    input = (input.data.new([word_to_ix[char]])).view(1,1)
            else:
                input = (input.data.new([top_index])).view(1,1)

            poetry.append(char)
            pre_char = char


        return poetry

3、生成诗歌

# -*- coding: utf-8 -*-
# generation.py
import os
from config import Config
import numpy as np
from model import PoetryModel
import torch


class Sample(object):
    def __init__(self):
        self.config = Config()
        self.device = torch.device('cuda') if self.config.use_gpu else torch.device('cpu')

        self.processed_data_path = self.config.processed_data_path
        self.model_path = self.config.model_path
        self.max_len = self.config.max_gen_len
        self.sentence_max_len = self.config.sentence_max_len

        self.load_data()
        self.load_model()

    def load_data(self):
        if os.path.exists(self.processed_data_path):
            data = np.load(self.processed_data_path, allow_pickle=True)
            self.data, self.word_to_ix, self.ix_to_word = data['data'], data['word2ix'].item(), data['ix2word'].item()

    def load_model(self):
        model = PoetryModel(len(self.word_to_ix),
                            self.config.embedding_dim,
                            self.config.hidden_dim,
                            self.device,
                            self.config.layer_num)
        map_location = lambda s, l: s
        state_dict = torch.load(self.config.model_path, map_location=map_location)
        model.load_state_dict(state_dict)
        model.to(self.device)
        self.model = model

    def generate_random(self, start_words='<START>'):
        """自由生成一首诗歌"""
        poetry = []
        sentence_len = 0

        input = (torch.Tensor([self.word_to_ix[start_words]]).view(1, 1).long()).to(self.device)
        hidden = self.model.init_hidden(self.config.layer_num, 1)

        for i in range(self.max_len):
            # 前向计算出概率最大的当前词
            output, hidden = self.model(input, hidden)
            top_index = output.data[0].topk(1)[1][0].item()

            # _probas = output.data[0].cpu().numpy()  # 在GPU上的Tensor没办法直接转numpy,先转到CPU再转成numpy
            # # 按照出现概率,对所有token倒序排列
            # p_args = np.argsort(-_probas)[:2]
            # # 排列后的概率顺序
            # p = _probas[p_args]
            # # 先对概率归一
            # p = p / sum(p)
            # # 再按照预测出的概率,随机选择一个词作为预测结果
            # choice_index = np.random.choice(len(p), p=p)
            # top_index = p_args[choice_index]

            char =self.ix_to_word[top_index]

            # 遇到终结符则输出
            if char == '<EOP>':
                break

            # 有8个句子则停止预测
            if char in ['。', '!']:
                sentence_len += 1
                if sentence_len == 8:
                    poetry.append(char)
                    break

            input = (input.data.new([top_index])).view(1, 1)
            poetry.append(char)


        return poetry

    def generate_head(self, head_sentence):
        """生成藏头诗"""
        poetry = []
        head_char_len = len(head_sentence)  # 要生成的句子的数量
        sentence_len = 0  # 当前句子的数量
        pre_char = '<START>'  # 前一个已经生成的字

        # 准备第一步要输入的数据
        input = (torch.Tensor([self.word_to_ix['<START>']]).view(1, 1).long()).to(self.device)
        hidden = self.model.init_hidden(self.config.layer_num, 1)

        for i in range(self.max_len):
            # 前向计算出概率最大的当前词
            output, hidden = self.model(input, hidden)
            top_index = output.data[0].topk(1)[1][0].item()

            # _probas = output.data[0].cpu().numpy()  # 在GPU上的Tensor没办法直接转numpy,先转到CPU再转成numpy
            # # 按照出现概率,对所有token倒序排列
            # p_args = np.argsort(-_probas)[:3]
            # # 排列后的概率顺序
            # p = _probas[p_args]
            # # 先对概率归一
            # p = p / sum(p)
            # # 再按照预测出的概率,随机选择一个词作为预测结果
            # choice_index = np.random.choice(len(p), p=p)
            # top_index = p_args[choice_index]

            char = self.ix_to_word[top_index]

            # 句首的字用藏头字代替
            if pre_char in ['。', '!', '<START>']:
                if sentence_len == head_char_len:
                    break
                else:
                    char = head_sentence[sentence_len]
                    sentence_len += 1
                    input = (input.data.new([self.word_to_ix[char]])).view(1,1)
            else:
                input = (input.data.new([top_index])).view(1,1)

            poetry.append(char)
            pre_char = char

        return poetry

    def generate_poetry(self, mode=1, head_sentence=None):
        """
        模式一:随机生成诗歌
        模式二:生成藏头诗
        :return:
        """
        poetry = ''
        if mode == 1 or (mode == 2 and head_sentence is None):
            poetry = ''.join(self.generate_random())
        if mode == 2 and head_sentence is not None:
            head_sentence = head_sentence.replace(',', u',').replace('.', u'。').replace('?', u'?')
            poetry = ''.join(self.generate_head(head_sentence))

        return poetry


if __name__ == '__main__':
    obj = Sample()
    poetry1 = obj.generate_poetry(mode=2, head_sentence="碧海潮生")
    print(poetry1)

4、配置文件

为了方便修改和调试模型,基本上所有的可以改的参数都放到配置模型文件中。很简单

# -*- encoding: utf-8 -*-
# config.py



class Config(object):
    processed_data_path = "data/tang.npz"  # 保存的数据预处理数据

    model_path = 'model/tang_5.pth'  # 载入的训练好的模型
    model_prefix = 'model/tang'  # 模型的保存

    batch_size = 64  # batch_size
    epoch_num = 10  # 训练的迭代次数epoch

    embedding_dim = 128  # 嵌入层的维度
    hidden_dim = 128  # LSTM的隐藏层的维度
    layer_num = 2  # LSTM的层数
    lr = 0.001  # 初始化学习率
    weight_decay = 1e-4  # Adam优化器的weight_decay参数

    use_gpu = True  # 是否使用GPU训练

    poetry_file = 'poetry.txt'  # 诗歌文件名称
    max_gen_len = 200  # 生成诗歌最长长度
    sentence_max_len = 4 # 生成诗歌的最长句子
    poetry_max_len = 125
    sample_max_len = poetry_max_len - 1

5、生成效果

怎么说呢,有点那味了。

桃殿开华碧色沈,

花间似水水间流。

影中云落风明月,

落日生光未出分。

碧云行自在,

海路几悠游。

潮暗遥还夜,

生游日见长。

6、结语

初次尝试用pytorch,有纰漏之处,还望指正,模型还有待改进。

参考:

基于循环神经网络(RNN)的古诗生成器_python_脚本之家 (jb51.net)手把手实现AI诗歌生成(AI写诗)https://www.jb51.net/article/137118.htm

(31条消息) TensorFlow练手项目二:基于循环神经网络(RNN)的古诗生成器_笔墨留年。-CSDN博客_rnn项目手把手实现AI诗歌生成(AI写诗)https://blog.csdn.net/aaronjny/article/details/79677457

版权声明:本文为博主 湖工商梁朝伟原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接: https://blog.csdn.net/m0_55970575/article/details/122651002

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
0
刚刚,arXiv论文数破200万,没有arXiv,就没有21世纪的科研突破
上一篇 2022年1月23日 下午2:43
【Python数据分析】数据挖掘建模——分类与预测——人工神经网络
下一篇 2022年1月23日 下午2:58

相关推荐

  • AMD GPU驱动,ROCM,Pytorch安装教程(A卡6700xt) 2023年6月26日
  • 基于1DCNN(一维卷积神经网络)的目标识别 2023年3月3日
  • 逐行对比LLaMA2和LLaMA模型源代码 2023年12月19日
  • 100天精通Python(实用脚本篇)——第111天:批量将PDF转Word文档(附上脚本代码) 2024年1月6日
  • AI绘图之DDIM 与 DDPM 2023年7月15日
  • 2023美国大学生数学建模竞赛ABCDEF题思路汇总 美赛建模思路 2023年3月1日
  • YOLOv5源码逐行超详细注释与解读(4)——验证部分val(test).py 2023年4月15日
  • 【AI开源大模型】GLM-130B:开放的中英双语预训练模型 2023年10月19日
  • Bresenham直线算法 2023年12月21日
  • GPT-3.5-turbo小白连接教程 2023年5月29日
  • 免费ai写作软件有哪些?分享10个给你 #知识分享#其他 2024年2月19日
  • chatgpt API key 获取及延续 2023年6月21日
  • ChatGPT、New Bing、文心一言、通义千问等 AI 工具到底哪个更AI? – 第二期 2023年10月6日
  • 如何使用Pytorch让网络模型加速训练?(autocast与GradScaler) 2022年5月21日
  • Tensorflow学习之tf.layers.dense() 2022年3月18日
  • IEEE Transactions模板中参考文献作者缩写、期刊名缩写 2023年8月16日

赞助商

聚圣源穿成反派女配她姐后我十项全能了食品公司免费起名咨询服务公司起名大全集党委书记七一讲话为钻石戒指起名字测起名与生辰八字暗黑破坏神2修改器udietoo傲慢的近义词猫qq表情开店如何起名大全1518公司起名测试打分猪年宝宝起名大全姓张师姓男孩起名简单好听酒吧起名字参考诗晴公交品客堂青盲姓童 起名用国学起名娃娃应该起什么名字欧起名老鼠会江湖策回眸过去tooopen左小青老公的个人资料公里数查询李准基陈翔caxa电子图板下载颖字女孩起名淀粉肠小王子日销售额涨超10倍罗斯否认插足凯特王妃婚姻让美丽中国“从细节出发”清明节放假3天调休1天男孩疑遭霸凌 家长讨说法被踢出群国产伟哥去年销售近13亿网友建议重庆地铁不准乘客携带菜筐雅江山火三名扑火人员牺牲系谣言代拍被何赛飞拿着魔杖追着打月嫂回应掌掴婴儿是在赶虫子山西高速一大巴发生事故 已致13死高中生被打伤下体休学 邯郸通报李梦为奥运任务婉拒WNBA邀请19岁小伙救下5人后溺亡 多方发声王树国3次鞠躬告别西交大师生单亲妈妈陷入热恋 14岁儿子报警315晚会后胖东来又人满为患了倪萍分享减重40斤方法王楚钦登顶三项第一今日春分两大学生合买彩票中奖一人不认账张家界的山上“长”满了韩国人?周杰伦一审败诉网易房客欠租失踪 房东直发愁男子持台球杆殴打2名女店员被抓男子被猫抓伤后确诊“猫抓病”“重生之我在北大当嫡校长”槽头肉企业被曝光前生意红火男孩8年未见母亲被告知被遗忘恒大被罚41.75亿到底怎么缴网友洛杉矶偶遇贾玲杨倩无缘巴黎奥运张立群任西安交通大学校长黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发妈妈回应孩子在校撞护栏坠楼考生莫言也上北大硕士复试名单了韩国首次吊销离岗医生执照奥巴马现身唐宁街 黑色着装引猜测沈阳一轿车冲入人行道致3死2伤阿根廷将发行1万与2万面值的纸币外国人感慨凌晨的中国很安全男子被流浪猫绊倒 投喂者赔24万手机成瘾是影响睡眠质量重要因素春分“立蛋”成功率更高?胖东来员工每周单休无小长假“开封王婆”爆火:促成四五十对专家建议不必谈骨泥色变浙江一高校内汽车冲撞行人 多人受伤许家印被限制高消费

聚圣源 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化