东京奥运会
前些天看东京奥运会的时候,18岁的突尼斯🇹🇳游泳运动员Ahmed Hafnaoui,获得男子400米自由泳冠军🏆本届奥运会爆冷选手!突尼斯只有这一个游泳运动员,还是游8道的,在最边边上,预选赛游得最慢的选手在决赛中成为第一名!
发现当他们国家国旗升起来的时候,感觉自己见都没见过;其实不光这个国家的国旗,奥运会上有好多国家的国旗我也都不认识,既然这样,今天就带大家来做一个国旗学习的网站吧,也算是给自己科普一下。
爬取网站信息存入数据库
-
在网上找了一个网站, 里面有全世界各国国旗大全,链接如下:
http://114.xixik.com/country-flag/
-
打开网站,就看到这样一个表格(如下图),心里想着这不就妥了吗, 国旗,国家,首都,人口,面积都有了,那我们直接直接这个表格岂不是可以拿到所有的信息了,当我按下F12打开谷歌浏览器的开发者工具查看的时候,发现让人有点小心塞的问题,这个表格里面的国旗竟然是缩略图,根本看不清。
-
没办法,只能再另想其他招了,再浏览浏览这个网站,发现这个表格上方还有一个表格里是有所有国家国旗的清晰图片的,并且每个国旗都有其对应的国家名称,那我们就只能先爬虫解析表格里的信息,然后根据国家名称找到对应的国旗图片链接,再一并存入我们的mysql数据库中。方便后面的网页制作。
-
网站页面简要分析
-
打开F12开发者工具获取headers - 每个浏览器都有自己的headers,因为headers要模仿你自己的浏览器向网页发送信息。
-
页面组成
-
国旗图片获取稍稍麻烦一些,先找到上面页面组成图片中展示的所有国家名称,然后根据国家名称去另一个表格里匹配到国旗图片,获取图片的链接,然后写入数据库表中
-
爬虫代码编写
#!/usr/bin/python3# -*- coding: utf-8 -*-# @Author : 陈龙# @公众号 : Python欢乐时光# @Date : 2021/08/21 12:51# @Software : PyCharm# @Version : Python 3.7.3import reimport collectionsimport pymysqlimport requestsfrom bs4 import BeautifulSoupclass CountryFlagSpider: def __init__(self): self.host = '121.4.102.161' self.user = 'root' self.password = 'cycl19940417' self.database = 'django_web' self.url = 'http://114.xixik.com/country-flag/' self.headers = { 'Host': '114.xixik.com', 'Connection': 'keep-alive', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' '(KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36' } # 用来存储我们爬取信息的字典 self.country_flag_list = list() def get_html_content(self): r = requests.get(self.url, headers=self.headers) r.encoding = 'gb2312' soup = BeautifulSoup(r.text, 'html.parser') return soup def get_country_info(self): soup = self.get_html_content() # 找到所有的行 trs = soup.findAll("div", {"class": "lindBox"})[6].findAll("tr") for tr in trs: tmp_dict = collections.OrderedDict() try: tds = tr.findAll('td')[1:] # 去除缩略图 tmp_dict['name'] = tds[0].text.strip() # 国家名称 tmp_dict['capital'] = tds[1].text.strip() # 国家首都 tmp_dict['population'] = tds[2].text.strip() # 国家人口 tmp_dict['area'] = tds[3].text.strip() # 国家面积 self.country_flag_list.append(tmp_dict) except Exception as e: print(e) def get_country_picture(self): soup = self.get_html_content() tds = soup.findAll("div", {"class": "lindBox"})[5].findAll("td") for td in tds: try: picture_url = td.find('img')['src'] # 获取国旗图标的src # 利用正则匹配字符串中的所有中文字符, '[\u4e00-\u9fa5]' 匹配中文 country_name = ''.join(re.findall(r'[\u4e00-\u9fa5]', td.text.strip())) # 获取国旗图标对应的名称 for each in self.country_flag_list: if each['name'] == country_name: each['picture'] = picture_url break except Exception as e: pass def save_into_db(self): self.get_country_info() self.get_country_picture() db = DbHelper(self.host, self.user, self.password, self.database) for each in self.country_flag_list: sql = 'insert into country_flag_info(name, capital, population, area, picture) values(%s, %s, %s, %s, %s)' values = list(each.values()) while len(values) < 5: values.append('') db.insert(sql, values) db.close()class DbHelper: def __init__(self, host, user, password, database): # 连接database self.conn = pymysql.connect(host=host, user=user, password=password, database=database, charset='utf8') # 得到一个可以执行SQL语句的光标对象 self.cursor = self.conn.cursor() def insert(self, sql, *args): try: # 执行SQL语句 self.cursor.execute(sql, *args) # 提交事务 self.conn.commit() except Exception as e: # 有异常,回滚事务 self.conn.rollback() def delete(self, sql, *args): try: # 执行SQL语句 self.cursor.execute(sql, *args) # 提交事务 self.conn.commit() except Exception as e: # 有异常,回滚事务 self.conn.rollback() def update(self, sql, *args): try: # 执行SQL语句 self.cursor.execute(sql, *args) # 提交事务 self.conn.commit() except Exception as e: # 有异常,回滚事务 self.conn.rollback() def query(self, sql, *args): # 执行SQL语句 self.cursor.execute(sql, *args) def close(self): self.cursor.close() self.conn.close()if __name__ == '__main__': obj = CountryFlagSpider() obj.save_into_db()
执行完上述代码后,网站上我们需要的数据就已经被我存储到mysql数据库中了,结果如下图
创建Django + Vue 的web网站
django创建项目及在服务器上mysql下载安装和配置在上一篇的公众号文章 从零开始在云服务器上搭建Django项目 中已经讲过了,如还没配置,请参照上一篇教程
安装node.js
-
新建一个文件夹
mkdir node
-
下载
wget https://npm.taobao.org/mirrors/node/v14.15.4/node-v14.15.4-linux-x64.tar.xz
-
解压
tar -xvf node-v14.15.4-linux-x64.tar.xz
-
重命名
mv node-v14.15.4-linux-x64 nodejs
-
建立软连接
ln -s /node/nodejs/bin/npm /usr/bin/npm
ln -s /node/nodejs/bin/node /usr/bin/node
-
查看
node -v
npm -v
-
添加淘宝镜像
npm config set registry https://registry.npm.taobao.org
-
查看修改结果
npm config get registry
安装 vue
-
安装
npm install vue
npm install -g vue-cli
npm install -g webpack
-
我们进入到我们的django_web项目,确保我们处在跟app同一级,然后使用:
vue init webpack firstvue
数据库同步
-
python manage.py makemigrations
-
python manage.py migrate
-
python manage.py inspectdb > pyweb/models.py
前端主要代码
<template> <div id="app"> <div class="line"></div> <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b"> <el-menu-item index="1">近期小制作</el-menu-item> <el-menu-item index="2"><a href="https://blog.csdn.net/sky5601" target="_blank">我的博客</a></el-menu-item> </el-menu> <el-tabs v-model="activeName" type="card" @tab-click="handleClick"> <el-tab-pane label="国旗常识学习" name="first"> <el-container> <el-header> <!-- <p>微信公众号:Python欢乐时光<p> --> <p>国旗常识在线学习<p> </el-header> <el-main> <div class="img_div" style="text-align: center;"> <el-image :src="src"></el-image> </div> <div style="text-align:center;margin:20px"> <el-button type="success" round @click="btn_show_detail">{{ btn_msg }}</el-button> </div> <div class="table_div"> <table class="ruletable" v-show="table_show"> <tbody> <tr> <td>国家:</td> <td>{{ content[0] }}</td> </tr> <tr> <td>首都:</td> <td>{{ content[1] }}</td> </tr> <tr> <td>人口:</td> <td>{{ content[2] }}</td> </tr> <tr> <td>面积</td> <td>{{ content[3] }}</td> </tr> </tbody> </table> </div> </el-main> <el-footer> <div style="text-align:center"> <el-button-group> <el-button type="primary" icon="el-icon-arrow-left" @click="func_prev_page">上一个</el-button> <el-button type="primary" @click="func_next_page">下一个<i class="el-icon-arrow-right el-icon--right"></i></el-button> </el-button-group> <p style="margin-top:20px">By 微信公众号:Python欢乐时光<p> </div> </el-footer> </el-container> </el-tab-pane> <el-tab-pane label="车标常识学习" name="second">功能正在开发中, 敬请期待</el-tab-pane> <el-tab-pane label="天气查询" name="third">功能正在开发中, 敬请期待</el-tab-pane> <el-tab-pane label="功能待开发" name="fourth" disabled>功能待开发</el-tab-pane> </el-tabs> </div></template><script>export default { data () { return { init_id: 1, content:['', '', '', ''], btn_msg:'查看详情', flag:0, table_show:false, tableData:[], activeIndex: '1', activeName: 'first', src: '' } }, mounted() { // document.title = '微信公众号搜索:Python欢乐时光' this.my_func(this.init_id) }, methods: { my_func: function(id) { let that = this this.axios({ url: '/country_flag', method: 'get', params: { 'id':id } }).then(res => { let res_data = res.data[0].fields console.log([res_data.name, res_data.capital, res_data.population, res_data.area]) that.content = [res_data.name, res_data.capital, res_data.population, res_data.area] console.log(res_data.picture) that.src = res_data.picture }).catch(err => { console.log(err) }) }, handleSelect(key, keyPath) { console.log(key, keyPath) }, handleClick(tab, event) { console.log(tab, event) }, func_prev_page() { if (this.init_id == 1) { this.init_id = 191 } else { this.init_id = this.init_id - 1 } this.my_func(this.init_id) }, func_next_page() { if (this.init_id === 191) { this.init_id = 1 } else { this.init_id = this.init_id + 1 } this.my_func(this.init_id) }, btn_show_detail() { if (this.flag === 0) { this.btn_msg = '隐藏详情' this.flag = 1 this.table_show = true } else { this.btn_msg = '查看详情' this.flag = 0 this.table_show = false } } }}</script><style>body { font-family: Helvetica, sans-serif;}p { font-size: 20px; text-align: center;}.img_div { padding-left:20%; padding-right:20%;}.table_div { padding-left:20%; padding-right:20%;}.ruletable{ width: 100%; border-collapse: collapse;}.ruletable th{ text-align: center;}.ruletable tr:nth-of-type(1){ border-top: 1px solid #FFDCDF;}.ruletable tr{ border-bottom: 1px solid #FFDCDF;}</style>
后端主要代码
# views.py 中class country_flag(APIView): def get(self,request): query_id = request.GET["id"] data = serializers.serialize("json", CountryFlagInfo.objects.filter(id=query_id)) return HttpResponse(data, content_type='application/json') # models.py 中class CountryFlagInfo(models.Model): name = models.CharField(max_length=50, db_collation='utf8_general_ci', blank=True, null=True) capital = models.CharField(max_length=50, db_collation='utf8_general_ci', blank=True, null=True) population = models.CharField(max_length=50, db_collation='utf8_general_ci', blank=True, null=True) area = models.CharField(max_length=50, db_collation='utf8_general_ci', blank=True, null=True) picture = models.TextField(blank=True, null=True) class Meta: managed = False db_table = 'country_flag_info'
完整的项目代码请在公众号下方回复 国旗 获取下载地址
最终效果演示
在电脑或者手机的浏览器中输入:http://121.4.102.161:8000/
PS: 由于我购买的服务器配置是最低的(别问我为什么不买配置高的,问就一个字,因为穷…),所以访问的时候可能会有些慢,请耐心等待几秒钟即可。见谅!
电脑端访问效果
手机端访问效果
结尾
如果觉得这篇文章还不错的话,欢迎点击文章右下角的“在看”, 期待您关注我的公众号 Python欢乐时光 ,转发给你身边有需要的朋友们。另外,本篇文章中所有的项目代码我都打包上传至百度网盘,公众号下方回复 国旗 获取下载地址。谢谢大家!