zoukankan      html  css  js  c++  java
  • python读取配置文件&&简单封装

    之前有做过把爬虫数据写到数据库中的练习,这次想把数据库信息抽离到一个ini配置文件中,这样做的好处在于可以在配置文件中添加多个数据库,方便切换(另外配置文件也可以添加诸如邮箱、url等信息)

    1.configparser模块

    python使用自带的configparser模块用来读取配置文件,配置文件的形式类似windows中的ini文件

    在使用前需要先安装该模块,使用pip安装即可

    2.configparser读取文件的基本方法

    (1)新建一个config.ini文件,如下

    (2)新建一个readconfig.py文件,读取配置文件的信息

    import configparser
    
    cf = configparser.ConfigParser()
    cf.read("E:Crawlerconfig.ini")  # 读取配置文件,如果写文件的绝对路径,就可以不用os模块
    
    secs = cf.sections()  # 获取文件中所有的section(一个配置文件中可以有多个配置,如数据库相关的配置,邮箱相关的配置,
    每个section由[]包裹,即[section]),并以列表的形式返回
    print(secs) options = cf.options("Mysql-Database") # 获取某个section名为Mysql-Database所对应的键 print(options) items = cf.items("Mysql-Database") # 获取section名为Mysql-Database所对应的全部键值对 print(items) host = cf.get("Mysql-Database", "host") # 获取[Mysql-Database]中host对应的值 print(host)

    上述代码运行结果如下,可以和config.ini进行对比 

    3.引入os模块,使用相对目录读取配置文件

    工程目录如下:

    readconfig.py:

    import configparser
    import os
    
    root_dir = os.path.dirname(os.path.abspath('.'))  # 获取当前文件所在目录的上一级目录,即项目所在目录E:Crawler
    cf = configparser.ConfigParser()
    cf.read(root_dir+"/config.ini")  # 拼接得到config.ini文件的路径,直接使用
    secs = cf.sections() # 获取文件中所有的section(一个配置文件中可以有多个配置,如数据库相关的配置,邮箱相关的配置,每个section由[]包裹,即[section]),并以列表的形式返回 print(secs) options = cf.options("Mysql-Database") # 获取某个section名为Mysql-Database所对应的键 print(options) items = cf.items("Mysql-Database") # 获取section名为Mysql-Database所对应的全部键值对 print(items) host = cf.get("Mysql-Database", "host") # 获取[Mysql-Database]中host对应的值 print(host)

    或者使用os.path.join()进行拼接

    import configparser
    import os
    
    root_dir = os.path.dirname(os.path.abspath('.'))  # 获取当前文件所在目录的上一级目录,即项目所在目录E:Crawler
    configpath = os.path.join(root_dir, "config.ini")
    cf = configparser.ConfigParser()
    cf.read(configpath)  # 读取配置文件
    secs = cf.sections() # 获取文件中所有的section(一个配置文件中可以有多个配置,如数据库相关的配置,邮箱相关的配置,每个section由[]包裹,即[section]),并以列表的形式返回 print(secs) options = cf.options("Mysql-Database") # 获取某个section名为Mysql-Database所对应的键 print(options) items = cf.items("Mysql-Database") # 获取section名为Mysql-Database所对应的全部键值对 print(items) host = cf.get("Mysql-Database", "host") # 获取[Mysql-Database]中host对应的值 print(host)

    4.通过读取配置文件,重新写一下之前的requests+正则表达式爬取猫眼电影的例子

    把读取配置文件readconfig.py和操作数据库handleDB.py分别封装到一个类中

    readconfig.py如下

    import configparser
    import os
    
    class ReadConfig:
        """定义一个读取配置文件的类"""
    
        def __init__(self, filepath=None):
            if filepath:
                configpath = filepath
            else:
                root_dir = os.path.dirname(os.path.abspath('.'))
                configpath = os.path.join(root_dir, "config.ini")
            self.cf = configparser.ConfigParser()
            self.cf.read(configpath)
    
        def get_db(self, param):
            value = self.cf.get("Mysql-Database", param)
            return value
    
    
    if __name__ == '__main__':
        test = ReadConfig()
        t = test.get_db("host")
        print(t)

    handleDB.py如下

    # coding: utf-8
    # author: hmk
    
    from common.readconfig import ReadConfig
    import pymysql.cursors
    
    
    class HandleMysql:
        def __init__(self):
            self.data = ReadConfig()
    
        def conn_mysql(self):
            """连接数据库"""
            host = self.data.get_db("host")
            user = self.data.get_db("user")
            password = self.data.get_db("password")
            db = self.data.get_db("db")
            charset = self.data.get_db("charset")
            self.conn = pymysql.connect(host=host, user=user, password=password, db=db, charset=charset)
            self.cur = self.conn.cursor()
    
        def execute_sql(self, sql, data):
            """执行操作数据的相关sql"""
            self.conn_mysql()
            self.cur.execute(sql, data)
            self.conn.commit()
    
        def search(self, sql):
            """执行查询sql"""
            self.conn_mysql()
            self.cur.execute(sql)
            return self.cur.fetchall()
    
        def close_mysql(self):
            """关闭数据库连接"""
            self.cur.close()
            self.conn.close()
    
    
    if __name__ == '__main__':
        test = HandleMysql()
        sql = "select * from maoyan_movie"
        for i in test.search(sql):
            print(i)

    最后的运行文件,调用前面的方法

    # coding: utf-8
    # author: hmk
    
    import requests
    import re
    from common import handleDB
    
    
    class Crawler:
        """定义一个爬虫类"""
        def __init__(self):
            self.db = handleDB.HandleMysql()
    @staticmethod
    def get_html(url, header): response = requests.get(url=url, headers=header) if response.status_code == 200: return response.text else: return None @staticmethod def get_data(html, list_data): pattern = re.compile(r'<dd>.*?<i.*?>(d+)</i>.*?' # 匹配电影排名 r'<p class="name"><a.*?data-val=".*?">(.*?)' # 匹配电影名称 r'</a>.*?<p.*?class="releasetime">(.*?)</p>' # 匹配上映时间 r'.*?<i.*?"integer">(.*?)</i>' # 匹配分数的整数位 r'.*?<i.*?"fraction">(.*?)</i>.*?</dd>', re.S) # 匹配分数小数位 m = pattern.findall(html) for i in m: # 因为匹配到的所有结果会以列表形式返回,每部电影信息以元组形式保存,所以可以迭代处理每组电影信息 ranking = i[0] # 提取一组电影信息中的排名 movie = i[1] # 提取一组电影信息中的名称 release_time = i[2] # 提取一组电影信息中的上映时间 score = i[3] + i[4] # 提取一组电影信息中的分数,这里把分数的整数部分和小数部分拼在一起 list_data.append([ranking, movie, release_time, score]) # 每提取一组电影信息就放到一个列表中,同时追加到一个大列表里,这样最后得到的大列表就包含所有电影信息 def write_data(self, sql, data): self.db.conn_mysql() try: self.db.execute_sql(sql, data) print('导入成功') except: print('导入失败') self.db.close_mysql() def run_main(self): start_url = 'http://maoyan.com/board/4' depth = 10 # 爬取深度(翻页) header = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Encoding": "gzip, deflate, sdch", "Accept-Language": "zh-CN,zh;q=0.8", "Cache-Control": "max-age=0", "Connection": "keep-alive", "Host": "maoyan.com", "Referer": "http://maoyan.com/board", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36"} for i in range(depth): url = start_url + '?offset=' + str(10 * i) html = self.get_html(url, header) list_data = [] self.get_data(html, list_data) for i in list_data: """这里的list_data参数是指正则匹配并处理后的列表数据(是一个大列表,包含所有电影信息,每个电影信息都存在各自的一个列表中; 对大列表进行迭代,提取每组电影信息,这样提取到的每组电影信息都是一个小列表,然后就可以把每组电影信息写入数据库了)""" movie = i # 每组电影信息,这里可以看做是准备插入数据库的每组电影数据 sql = "insert into maoyan_movie(ranking,movie,release_time,score) values(%s, %s, %s, %s)" # sql插入语句 self.write_data(sql, movie) if __name__ == '__main__': test = Crawler() test.run_main()
  • 相关阅读:
    time 模块学习
    day 14 自定义模块,常用模块 time .datetime ,time 模块
    day 13 课后作业
    day 12 课后作业
    day 11课后作业
    树状数组最值
    hdu 1059 Dividing bitset 多重背包
    XVII Open Cup named after E.V. Pankratiev. XXI Ural Championship
    最长公共子序列板/滚动 N^2
    Uva 10635
  • 原文地址:https://www.cnblogs.com/hanmk/p/9843136.html
Copyright © 2011-2022 走看看