使用爬虫+Flask获取世界国旗数据和孩子一起学习

作为父亲的失职

现在是凌晨三点半,我完成了今天的文章。之所以熬这么晚,主要是因为我这一对儿不听话的双胞胎。

今天孩子幼儿园发来了一张身心发展评价表,其中有一项社会文化的栏目,他俩都是一颗星(差),其中涉及的内容有:

会朗读和演唱简单的民间歌曲,喜欢听世界著名童话故事,能认识1-2个邻国的国旗。

他俩这项都是差让我有些愧疚,自问平时工作太忙,偶尔回家早些也想躺着玩会儿手机,陪孩子的时间不多。所谓子不教父之过,那么针对这个差我能做些什么?大概能认识1-2个邻国的国旗这项比较容易

数据获取

在网上翻了翻,找到一个统计国家、国旗、人口、面积的网站:

http://114.xixik.com/country-flag/

本来想着直接从第二张图的位置去获取,但发现国旗是缩略图,太小看不清。所以只好把这两张图拼接一起。通过国家名字进行关联了...

说干就干.....

网站分析

网站总体来说比较简单,统一的样式通过class的lindBox即可获取,下图微网站结构拼接图:

图片的下载和国家数据分别在第6个和第7个lindBox,对应index的5,6

图片解析img的src一级td的text,将名字对应保存即可

国家数据就更简单了直接for循环所有tr,使用正则格式化下就OK了

批量下载与存储

图片下载使用request.get(url)获取二进制数据,之后写入文件即可,至于目录,我们放在static/images下,至于为什么放这个目录,一会儿说....

国家数据由于不多,所以直接使用SQLite存储即可(其实存文本也行,但不方便后面使用)...

梳理OK,上代码:

# -*- coding: utf-8 -*-
# @Author   : 王翔
# @JianShu  : 清风Python
# @Date     : 2019/6/11 2:19
# @Software : PyCharm
# @version  :Python 3.6.8
# @File     : CountryFlagCrawler.py.py

import requests
from bs4 import BeautifulSoup
import re
import os
from db_maker import DB_Maker as DB


class CountryFlagCrawler:
    def __init__(self):
        self.url = "http://114.xixik.com/country-flag/"
        self.headers = {
            'Host': "114.xixik.com",
            'Connection': 'keep-alive',
            'user-agent': ('Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 '
                           '(KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36')
        }
        self.db = DB()
        self.save_path = 'static/images'

    def check_dir(self):
        if not os.path.exists(self.save_path):
            os.mkdir(self.save_path)

    def get_response(self, url, params=None):
        r = requests.get(url, headers=self.headers, params=params)
        r.encoding = 'gb2312'
        soup = BeautifulSoup(r.text, "lxml")
        return soup

    def down_load_flag(self):
        soup = self.get_response(self.url)
        tds = soup.findAll("div", {"class": "lindBox"})[5].findAll("td")
        for td in tds:
            try:
                picture_url = td.find('img')['src']
                country_name = '%s.gif' % re.sub('s', '', td.text)
                print("Download %s" % country_name)
                r = requests.get(picture_url)
                with open(os.path.join(self.save_path, country_name), 'wb') as f:
                    f.write(r.content)
            except:
                pass
        # contury_info
        country_list = []
        trs = soup.findAll("div", {"class": "lindBox"})[6].findAll("tr")
        for tr in trs:
            try:
                info = list(map(lambda x: re.sub('s|,', '', x.text), tr.findAll('td')[1:]))
                if len(info) == 4:
                    # 数据错误补充:
                    if info[0] == '俄罗斯':
                        country_list.append([info[0], info[1], int(info[2]), 17098246])
                    else:
                        country_list.append([info[0], info[1], int(info[2]), int(info[3])])
            except:
                pass

        sql = "insert into country_flag (country,capital,population,area) values " 
              "(?,?,?,?)"
        for line in sorted(country_list, key=lambda x: x[3], reverse=True):
            self.db.insert(sql, line)


if __name__ == '__main__':
    main = CountryFlagCrawler()
    main.check_dir()
    main.down_load_flag()

文中引用到了db_maker,是通过DBUtils封装的链接池,对这个感兴趣的可以看下我之前的文章:

决战高考,帮你秒变成语之王

看下效果吧:

数据获取.gif

数据获取完成,看到视频上的目录,大家应该知道下一步要做什么了。对通过Flask创建一个Web服务器。

Flask编写国旗学习网站

我们拿到了国旗与国家的数据,但孩子会喜欢学习吗?答案是NO,他俩只喜欢玩我和媳妇儿的手机。那么如果可以做成网站,在电脑上搭建web服务,一起和孩子通过手机访问学习,是不效果更好?走起....

我们要打到的效果大概是:访问网站,弹出国旗,测试后查看正确答案,支持上下翻页。先看看效果:

网站效果.gif

怎么做?其实很简单,引入bootstrap的css,然后网站设计图片、按钮、表格集中class,js简单设置下div的显隐就OK了。整体代码目录如下:

附上代码吧:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="{{url_for('static',filename='favicon.ico')}}">
    <title>父子学习认国旗</title>
    <!-- Bootstrap core CSS -->
    <link href="{{url_for('static',filename='css/bootstrap.min.css')}}" rel="stylesheet">
    <!-- Custom styles for this template -->
    <link href="{{url_for('static',filename='css/cover.css')}}" rel="stylesheet">
    <script type="text/javascript">
    function display(id) {
        var traget = document.getElementById(id);
        if (traget.style.display == "none") {
            traget.style.display = "";
        } else {
            traget.style.display = "none";
        }
    }
    </script>
</head>

<body>
    <div class="site-wrapper">
        <div class="site-wrapper-inner">
            <div class="cover-container">
                <div class="masthead clearfix">
                    <row>
                        <h1 class="cover-heading">父子学习认国旗</h1>
                        <div class="inner">
                            <p><img src="{{url_for('static',filename='images/%s.gif'|format(content[1]))}}" class="img-rounded"></p>
                            <p> <input type="submit" class="btn  btn-success" value="查看详情..." onclick="display('lb')"></p>
                        </div>
                        <div class="inner cover">
                            <div id="lb" class="inner cover" style="display:none">
                                <div>
                                    <table class="table table-bordered">
                                        <tbody>
                                            <tr>
                                                <td>国家:</td>
                                                <td>{{content[1]}}</td>
                                            </tr>
                                            <tr>
                                                <td>首都:</td>
                                                <td>{{content[2]}}</td>
                                            </tr>
                                            <tr>
                                                <td>人口:</td>
                                                <td>{{content[3]}}</td>
                                            </tr>
                                            <tr>
                                                <td>面积</td>
                                                <td>{{content[4]}}</td>
                                            </tr>
                                        </tbody>
                                    </table>
                                </div>
                            </div>
                        </div>
                    </row>
                    <div class="mastfoot">
                        {%if content[0] ==1%}
                        <a href="" disabled="disabled" class="btn btn-primary btn-sm">上一页</a>
                        {%else%}
                        <a href="{{url_for('index',country_id=content[0]-1)}}" class="btn btn-primary btn-sm">上一页</a>
                        {%endif%}
                        <a href="{{url_for('index',country_id=content[0]+1)}}" class="btn btn-primary btn-sm">下一页</a>
                        <div class="inner">
                            <p>by <a href="https://www.jianshu.com/u/d23fd5012bed">清风Python</a></p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>

</html>
# -*- coding: utf-8 -*-
# @Author   : 王翔
# @JianShu  : 清风Python
# @Date     : 2019/6/11 3:24
# @Software : PyCharm
# @version  :Python 3.6.8
# @File     : CountryFlagFlask.py

from flask import Flask, render_template, g,
from db_maker import DB_Maker as DB

app = Flask(__name__)


@app.before_request
def connect():
    g.db = DB()


@app.route('/')
@app.route('/<int:country_id>')
def index(country_id=1):
    result = g.db.fetch_one("select * from country_flag where id=%s" % country_id)
    print(result)
    return render_template("index.html", content=result)


if __name__ == '__main__':
    app.run(host='0.0.0.0')

手机访问

手机访问效果.gif

明天早点回家,跟孩子一起收集上学习认国旗吧,哈哈.....

好了,今天的内容就到这里,如果觉得有帮助,记得点赞支持。欢迎大家关注我的公众号【清风Python】,

整套代码和数据,我会打包放在百度云盘,公众号回复关键字 国旗 即可获得下载地址。

来源:清风Python

原文地址:https://www.cnblogs.com/2020-zhy-jzoj/p/13165928.html