首页
畅所欲言
友情链接
壁纸大全
数据统计
推荐
工具箱
在线白板
Search
1
职教云小助手重构更新,职教云助手最新版下载地址【已和谐】
14,039 阅读
2
职教云-智慧职教,网课观看分析(秒刷网课)
11,353 阅读
3
gradle-5.4.1-all.zip下载
9,342 阅读
4
职教云-智慧职教,签到补签分析(逆天改命系列)
8,140 阅读
5
一个优秀的程序员从写文档开始:免费领14个月语雀云笔记会员
6,992 阅读
学习笔记
Web
Python
转载文章
算法刷题
JS逆向
综合笔记
安卓
物联网
Java
C
资源收集
软件收藏
网络资源
影视专辑
TED英语角
随便写写
随手拍
登录
/
注册
Search
Lan
累计撰写
615
篇文章
累计收到
629
条评论
首页
栏目
学习笔记
Web
Python
转载文章
算法刷题
JS逆向
综合笔记
安卓
物联网
Java
C
资源收集
软件收藏
网络资源
影视专辑
TED英语角
随便写写
随手拍
页面
畅所欲言
友情链接
壁纸大全
数据统计
推荐
工具箱
在线白板
搜索到
450
篇与
的结果
2020-10-04
汤圆创作小说检索信息采集
前段时间,因为一些原因,所以需要对这个汤圆创作的小说进行检索,于是写了几行python代码解析了一下搜索出来的结果的信息。# -*- coding: utf-8 -*- """ ------------------------------------------------- @ Author :Lan @ Blog :www.lanol.cn @ Date : 2020/9/30 @ Description:I'm in charge of my Code ------------------------------------------------- """ import requests import parsel for i in range(1, 10094): url = f'https://www.itangyuan.com/search/book/%E4%B8%80%20%E7%94%9F.html?page={i}' res = requests.get(url).text xpathFile = parsel.Selector(res) author = xpathFile.xpath("//p[@class='author']/a/text()").extract() name = xpathFile.xpath("//p[@class='bname']/a/text()").extract() info = xpathFile.xpath("//p[@class='rw_info']/text()").extract() for index, value in enumerate(name): if '一' in value.replace(' ', '') and '生' in value.replace(' ', ''): if int(info[index].split('阅读')[0].replace(' ', '')) < 1000: print(value, author[index], info[index].split('/')[-1]) print(f'已检测至第{i}页')大概就是搜索出所有小说名包含一和生字且阅读量小于1000的。
2020年10月04日
895 阅读
0 评论
0 点赞
2020-09-29
Django设置全局模板变量
最近由于需要,之前做的一个项目需要将图片文件转移至COS对象储存,因为服务器网络不行,图片加载太慢。经过一番猛如虎的操作,目的还是达到了。但是问题来了,图片上传好了,那怎么访问呢,我一开始想的是在数据里加一个表,就是用来存一些默认的字段。但是每次都得去取一次,然后还得返回,感觉实在有点浪费,于是想着有没有全局模板变量,就像我在模板中可以直接调用request.user一样。经过百度,找到了答案。先在一个view中添加你要返回的默认值然后在settings中的Templates->OPTIONS->context_processors进行注册(大概是这样叫吧,个人理解)然后就可以直接在模板中引用这个值了。
2020年09月29日
677 阅读
0 评论
0 点赞
2020-09-26
安卓在子线程传值给主线程,通过Handler传值
昨晚上在进行http请求获取数据并修改listview的时候遇到了一个问题Only the original thread that created a view hierarchy can touch its views大概意思就是:只有创建了视图层级的原始线程才可以修改这个视图于是我百度了一下,然后大概解决方案是这样子的,子线程通过handler传值给主线程,主线程接收后,再进行修改listview。Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == 1) { Bundle data = msg.getData(); String val = data.getString("value"); //设置UI tvCode.setText(val); Log.i(TAG, "请求结果:" + val); } else if (msg.what ==0) { Toast.makeText(getApplicationContext(),"请求资源不成功",Toast.LENGTH_LONG).show(); } } }; /** * 处理网络请求的线程 */ private class RequestThread extends Thread { @Override public void run() { //网络请求 String string = 请求结果 Message msg = new Message(); Bundle data = new Bundle(); //将获取到的String装载到msg中 data.putString("value", string); msg.setData(data); msg.what = 1; //发消息到主线程 handler.sendMessage(msg); } } //点击事件启动新线程 public void test(View v){ new RequestThread().start(); }解决方法原链接:https://blog.csdn.net/LJX_ahut/article/details/89432576经过实践着实有用。获取前:获取后:MainActivity.java代码package ink.cik.logininfoapp; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint; import android.net.wifi.aware.DiscoverySession; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.Menu; import android.view.View; import android.widget.Adapter; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.Toast; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.util.ArrayList; import java.util.List; import ink.cik.logininfoapp.eneity.userInfo; import ink.cik.logininfoapp.help.httpHelper; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class MainActivity extends AppCompatActivity { private final Gson gson = new Gson(); @SuppressLint("HandlerLeak") Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == 1) { Bundle data = msg.getData(); String val = data.getString("value"); List<userInfo> userInfoList = parseJson(val); ListView listView = (ListView) findViewById(R.id.listInfo); ArrayList<String> list = new ArrayList<String>();//数据源集合创建 for (userInfo userInfo : userInfoList) { list.add(userInfo.getUserName()); } ArrayAdapter<String> adapter = new ArrayAdapter<String>( MainActivity.this, android.R.layout.simple_list_item_1, list ); listView.setAdapter(adapter); } else if (msg.what == 0) { Toast.makeText(MainActivity.this, "数据获取失败,请检查网络!", Toast.LENGTH_SHORT); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.searchButton); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getAll(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu, menu); return true; } private void getAll() { final httpHelper httpHelper = new httpHelper(); new Thread(new Runnable() { @Override public void run() { try { String res = httpHelper.httpGet("https://api.565.ink/login/getAll?passwd=lanol666"); Log.d("结果:", res); Message msg = new Message(); Bundle data = new Bundle(); //将获取到的String装载到msg中 data.putString("value", res); msg.setData(data); msg.what = 1; handler.sendMessage(msg); } catch (Exception e) { e.printStackTrace(); } } }).start(); } private List<userInfo> parseJson(String JsonData) { Gson gson = new Gson(); List<userInfo> userInfoList = gson.fromJson(JsonData, new TypeToken<List<userInfo>>() { }.getType()); return userInfoList; } }
2020年09月26日
1,012 阅读
0 评论
0 点赞
2020-09-24
Android在子线程显示Toast闪退,Can"t toast on a thread that has not called Loop
新建一个类toastHelppackage ink.cik.logininfoapp.eneity; import android.content.Context; import android.os.Looper; import android.widget.Toast; public class toastHelp { static Toast toast = null; public static void show(Context context, String text) { try { if (toast != null) { toast.setText(text); } else { toast = Toast.makeText(context, text, Toast.LENGTH_SHORT); } toast.show(); } catch (Exception e) { //解决在子线程中调用Toast的异常情况处理 Looper.prepare(); Toast.makeText(context, text, Toast.LENGTH_SHORT).show(); Looper.loop(); } } }然后需要用的时候直接调用toastHelp.show(LoginActivity.this, responseInfo.getInfo());
2020年09月24日
1,024 阅读
0 评论
0 点赞
2020-09-24
利用okhttp3调用接口,用gson解析json数据
开心,总算搞好了调用接口获取所有用户信息,然后打印出来了。MainActivity.javapackage ink.cik.logininfoapp; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.io.IOException; import java.util.List; import java.util.Map; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class MainActivity extends AppCompatActivity { private final Gson gson = new Gson(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.loginButton); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { EditText userName = findViewById(R.id.userName); EditText passWord = findViewById(R.id.passWord); Toast.makeText(MainActivity.this, userName.toString(), Toast.LENGTH_SHORT).show(); verLogin(); } }); } private void verLogin() { new Thread(new Runnable() { @Override public void run() { try { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url("https://api.565.ink/login/getAll?passwd=lanol666").build(); Response response = client.newCall(request).execute(); String responsedata = response.body().string(); Log.d("返回数据:", responsedata); parseJson(responsedata); } catch (IOException e) { e.printStackTrace(); } } }).start(); } private void parseJson(String JsonData) { Gson gson = new Gson(); List<userInfo> userInfoList = gson.fromJson(JsonData, new TypeToken<List<userInfo>>() { }.getType()); for (userInfo userInfo : userInfoList) { Log.d("信息:", userInfo.getUserName()); } } }userInfo.javapackage ink.cik.logininfoapp; public class userInfo { private int id; private String userName; private String passWord; private String nation; private int age; private String tel; public int getAge() { return age; } public String getNation() { return nation; } public int getId() { return id; } public String getPassWord() { return passWord; } public String getTel() { return tel; } public String getUserName() { return userName; } public void setAge(int age) { this.age = age; } public void setId(int id) { this.id = id; } public void setNation(String nation) { this.nation = nation; } public void setPassWord(String passWord) { this.passWord = passWord; } public void setTel(String tel) { this.tel = tel; } public void setUserName(String userName) { this.userName = userName; } }
2020年09月24日
1,090 阅读
0 评论
0 点赞
2020-09-23
Android OKHttp发送get网络请求实例
今天总算把安卓的网络请求弄了一下了。获取的是我自己做的接口:https://api.565.ink/one/随机一句英语,不得不说换一门语言,写法上真的有点不适应。MainActivify.javapackage ink.cik.firsthttpapp; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import java.io.IOException; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class MainActivity extends AppCompatActivity { TextView responseText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.btnSyncTest); responseText = findViewById(R.id.response_text); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d("点击事件", "点击发送请求按钮"); sendRequest(); } }); } private void sendRequest() { //开启线程发送请求 new Thread(new Runnable() { @Override public void run() { try { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url("https://api.565.ink/one/").build(); Response response = client.newCall(request).execute(); String responseData = response.body().string(); showResponse(responseData); } catch (IOException e) { e.printStackTrace(); } } }).start(); } private void showResponse(final String response) { runOnUiThread(new Runnable() { @Override public void run() { responseText.setText(response); } }); } }AndroidMainifest.xml<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ink.cik.firsthttpapp"> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>activity_main.xml<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btnSyncTest" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="同步测试" /> <Button android:id="@+id/btnAsyncTest" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="异步测试" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <EditText android:id="@+id/etId" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="6" android:hint="输入用户编号" android:inputType="number" /> <Button android:id="@+id/btnParamTest" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="doParamTest" android:text="传参测试" /> </LinearLayout> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/response_text" android:layout_width="match_parent" android:layout_height="match_parent" /> </ScrollView> </LinearLayout>build.gradleapply plugin: 'com.android.application' android { compileSdkVersion 30 buildToolsVersion "30.0.2" defaultConfig { applicationId "ink.cik.firsthttpapp" minSdkVersion 30 targetSdkVersion 30 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.1' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' implementation 'com.squareup.okhttp3:okhttp:4.9.0' implementation 'com.squareup.okio:okio:2.8.0' }总结一下踩得一些坑。坑一:导入okhttp包导错了地方。书上说,要在build.gradle中导入okhttp和okio于是乎。。这两个里面果断的选择了第一个,因为名字是自己取的,按照python来说,默认的都是系统的。结果出错了,其实是Module:app这个坑二:本来我是本地搭建的环境,然后电脑端自己修改的hosts,将lan指向了127.0.0.1于是乎。坑三:原本用的http,结果不行,百度发现得https
2020年09月23日
1,217 阅读
2 评论
1 点赞
2020-09-23
django ImportExportModelAdmin自定义导出数据
官方文档:django-import-exportdjango 导出数据到excel借助官方文档的一些数据进行理解:class Author(models.Model): name = models.CharField(max_length=100) def __str__(self): return self.name class Category(models.Model): name = models.CharField(max_length=100) def __str__(self): return self.name class Book(models.Model): name = models.CharField('Book name', max_length=100) author = models.ForeignKey(Author, blank=True, null=True) author_email = models.EmailField('Author email', max_length=75, blank=True) imported = models.BooleanField(default=False) published = models.DateField('Published', blank=True, null=True) price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True) categories = models.ManyToManyField(Category, blank=True) def __str__(self): return self.name创建导入或导出的资源from import_export import resources from core.models import Book class BookResource(resources.ModelResource): class Meta: model = Book # 要影响哪些模型字段将包含在导入导出的资源中,请使用fields(自定义)选项将字段列入白名单 fields = ('id', 'name', 'price',) # 或将exclude(自定义)字段列入黑名单的选项 exclude = ('imported', ) # export_order(自定义) 选项设置导出字段的显式顺序 export_order = ('id', 'price', 'author', 'name')现在已经创建了一个模型资源,我们可以导出到csv文件>>> from app.admin import BookResource >>> dataset = BookResource().export() >>> print(dataset.csv) id,name,author,author_email,imported,published,price,categories 2,Some book,1,,0,2012-12-05,8.85,1定义ModelResource字段时,可以遵循模型关系,class BookResource(resources.ModelResource): class Meta: model = Book # 注意这里是中间是两个下划线,表示链式调用的模型关系 fields = ('author__name',)定义ModelResource属性时,可以遵循模型关系,from import_export.fields import Field class BookResource(resources.ModelResource): ''' 自定义属性时,attribute所对应的值可以是链式调用,author__name实际得到的就是作者的名字, 但是在查询时记得使用select_related(),以保证在查询时可以将所关联的外键数据一块查出,否则无法使用链式调用, 最下面会有完整的例子说明 ''' author_name = Field(attribute='author__name', column_name='作者名字') class Meta: model = Book # fields = () export_order = ('id', 'price', 'author', 'name','author_name')可以覆盖资源字段以更改其某些选项`from import_export.fields import Field class BookResource(resources.ModelResource): published = Field(attribute='published', column_name='published_date') class Meta: model = Book可以添加目标模型中不存在的其他字段from import_export.fields import Field class BookResource(resources.ModelResource): myfield = Field(column_name='myfield',attribute='组织数据时自定义的名字') class Meta: model = Bookimport_export.fields.Field可用的属性:导出时进行高级数据处理:''' 并非所有数据都可以从对象/模型属性中轻松提取。 为了在导出时将复杂的数据模型转换为(通常更简单)的已处理数据结构,dehydrate_<fieldname>应定义方法: ''' from import_export.fields import Field class BookResource(resources.ModelResource): full_title = Field() class Meta: model = Book def dehydrate_full_title(self, book): return '%s by %s' % (book.name, book.author.name)在这种情况下,导出看起来像这样:>>> from app.admin import BookResource >>> dataset = BookResource().export() >>> print(dataset.csv) full_title,id,name,author,author_email,imported,published,price,categories Some book by 1,2,Some book,1,,0,2012-12-05,8.85,1自定义小部件一个ModelResource创建与给定字段类型的默认控件的字段。如果小部件应使用不同的参数初始化,请设置widgets字典。在此示例窗口小部件中,该published字段被覆盖以使用其他日期格式。此格式将同时用于导入和导出资源。class BookResource(resources.ModelResource): class Meta: model = Book widgets = { 'published': {'format': '%d.%m.%Y'}, }应用场景:视图是这样的:渲染上面的视图主要用到了两个表:观看表和分享表class WatchStatistics(models.Model): """ 观看 """ # 支持匿名用户 user = models.ForeignKey(User, null=True) course = models.ForeignKey(VideoInfo, related_name="watch_course") ip = models.CharField(max_length=31) duration = models.DecimalField(decimal_places=2, max_digits=12, default=0.00, null=True) createDate = models.DateTimeField(auto_now_add=True) enterprise = models.ForeignKey(Enterprise, related_name="watch_enterprise") startDate = models.DateTimeField() endDate = models.DateTimeField() type = models.CharField(max_length=50, choices=USER_TYPE_CHOICES, default=REGISTER_USER) class DistributionRelationship(models.Model): """ 分享 """ # 受邀人 invited_user = models.ForeignKey(User, related_name='invited_user', null=True) # 分享人 share_user = models.ForeignKey(User, related_name='share_user', null=True) course = models.ForeignKey("course.VideoInfo", related_name="relationship_course") createDate = models.DateTimeField(auto_now_add=True) updateDate = models.DateTimeField(auto_now=True)难度就在于把两张表数据糅合在一块,并且还需要一些自定义的列,导出excel后端代码:from import_export import resources from import_export import fields from .models import WatchStatistics class WatchStatisticsResource(resources.ModelResource): # attribute所对应的值,中间是两个下划线,链式调用 title = fields.Field(column_name='课程名称', attribute='course__title') user = fields.Field(column_name='用户', attribute='user__owner__name') tel = fields.Field(column_name='电话号码', attribute='user__owner__tel') view_count = fields.Field(column_name='访问次数', attribute='view_count') total_duration = fields.Field(column_name='累计观看时间(分钟)', attribute='total_view_time') endDate = fields.Field(column_name='最后观看时间', attribute='endDate') # share_user 要对应到group_user.share_user share_user = fields.Field(column_name='分享人', attribute='share_user') class Meta: model = WatchStatistics fields = ( ) export_order = ('title', 'user', 'tel', 'view_count', 'total_duration', 'endDate', 'share_user') widgets = { 'endDate': {'format': '%Y-%m-%d %H:%M:%S'}, } @method_decorator(login_required, name='dispatch') class AdminExport(View): resource_model = None redirect_space = None model_class = None datetime_fields = [] search_fields = [] default_filters = {} prefix = "" default_order_sort_field = ['id'] def export(self, request, queryset): content_type = request.GET.get('content_type', 'application/vnd.ms-excel') dataset = self.resource_model().export(queryset=queryset) filename = "%s_%s" % (self.prefix, utils.datetime2string()) if "excel" in content_type: suffix = "xls" elif "csv" in content_type: suffix = "csv" else: messages.error(request, u'导出格式有误!') logger.info("export format error") return redirect(self.redirect_space) content = getattr(dataset, suffix) # # content_type 这里响应对象获得了一个特殊的mime类型,告诉浏览器这是个excel文件不是html response = HttpResponse(content, content_type=content_type) # # 这里响应对象获得了附加的Content-Disposition协议头,它含有excel文件的名称,文件名随意,当浏览器访问它时,会以"另存为"对话框中使用它. response['Content-Disposition'] = 'attachment; filename=%s' % ( '{}.{}'.format(filename, suffix),) return response class WatchStatisticsExport(AdminExport): resource_model = WatchStatisticsResource redirect_space = 'analysis:time' model_class = WatchStatistics prefix = "watchstatistics" datetime_fields = [] search_fields = [] default_filters = {} def get(self, request): course_id = self.request.GET.get('course_id') start_time = self.request.GET.get('start_time') end_time = self.request.GET.get('end_time') watchstatistics_list = WatchStatistics.objects.filter(course=course_id).select_related().order_by('-endDate') if start_time: watchstatistics_list = watchstatistics_list.filter(endDate__gte=start_time) if end_time: watchstatistics_list = watchstatistics_list.filter(endDate__lte=end_time) # 查询出当前课程的分享表 distribution_list = DistributionRelationship.objects.filter(course=course_id).select_related() invited_user_list = [] base_user = OrderedDict() for watch in watchstatistics_list: user = base_user.setdefault(watch.user_id, []) user.insert(0,watch) # 将分享表里受邀人的id所在记录append for dis in distribution_list: # 将拥有受邀人的id记录在列表,加入多条的话,说明同一直播,此人被不同的人邀请进来或者分享人多次访问会造成多条记录 if dis.invited_user.id == watch.user_id: user.append(dis) invited_user_list.append(watch.user_id) watch_records = [] for user_id, users in base_user.items(): # 判断如果有分享的记录,则excel加入邀请人 if not invited_user_list: group_user = users[0] group_user.view_count = len(users) total_view_time = sum([u.duration for u in users]) group_user.total_view_time = total_view_time watch_records.append(group_user) else: # 判断如果学员与受邀人一致,则分开处理 group_user = users[0] if group_user.user.id in invited_user_list: # 同一个人在同一直播被多人邀请过,查找次数 num = invited_user_list.count(group_user.user.id) # 减去分享记录和访问次数 group_user.view_count = len(users)-num total_view_time = sum([u.duration for u in users[:-num]]) group_user.total_view_time = total_view_time share_user = users[-1].share_user.owner.name group_user.share_user =share_user else: group_user.view_count = len(users) total_view_time = sum([u.duration for u in users]) group_user.total_view_time = total_view_time group_user.share_user = '无' watch_records.append(group_user) return self.export(request, queryset=watch_records)效果如图:
2020年09月23日
951 阅读
0 评论
0 点赞
1
...
28
29
30
...
65