zoukankan      html  css  js  c++  java
  • 使用爬虫+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

  • 相关阅读:
    bean的注入方式
    Spring中的IOC
    BeanFactory和ApplicationContext的区别
    mysql出现锁表 com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
    centos防火墙
    sql中union和union all的区别
    Sql语句中IN和exists的区别及应用
    ROLLUP,CUBE,GROUPPING详解
    通过WinRM在本机执行云服务器脚本,更新git代码
    Sqlserver2012评估期已过问题解决
  • 原文地址:https://www.cnblogs.com/2020-zhy-jzoj/p/13165928.html
Copyright © 2011-2022 走看看