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()
  • 相关阅读:
    SQL Server 索引基本概念与优化
    将Heap RID转换成RID格式
    有关DeadLock的文章列表
    sql报字段过大的错误解决方法
    查询当天数据(mysql)
    cookie和session的区别
    get和post的区别
    jq点击切换按钮最简洁代码
    js提示确认删除吗
    thinkphp解决分页后序列号自增的问题
  • 原文地址:https://www.cnblogs.com/hanmk/p/9843136.html
Copyright © 2011-2022 走看看