Python讀取配置文件-ConfigParser的二次封裝方法
Python讀取配置文件-ConfigParser二次封裝
直接上上代碼
test.conf
[database] connect = mysql sleep = no test = yes
config.py
# -*- coding:utf-8 -*-
__author__ = 'guoqianqian'
import os
import ConfigParser
import os
current_dir = os.path.abspath(os.path.dirname(__file__))
class OperationalError(Exception):
"""operation error."""
class Dictionary(dict):
""" custom dict."""
def __getattr__(self, key):
return self.get(key, None)
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
class Config:
def __init__(self, file_name="test", cfg=None):
"""
@param file_name: file name without extension.
@param cfg: configuration file path.
"""
env = {}
for key, value in os.environ.items():
if key.startswith("TEST_"):
env[key] = value
config = ConfigParser.ConfigParser(env)
if cfg:
config.read(cfg)
else:
config.read(os.path.join(current_dir, "conf", "%s.conf" % file_name))
for section in config.sections():
setattr(self, section, Dictionary())
for name, raw_value in config.items(section):
try:
# Ugly fix to avoid '0' and '1' to be parsed as a
# boolean value.
# We raise an exception to goto fail^w parse it
# as integer.
if config.get(section, name) in ["0", "1"]:
raise ValueError
value = config.getboolean(section, name)
except ValueError:
try:
value = config.getint(section, name)
except ValueError:
value = config.get(section, name)
setattr(getattr(self, section), name, value)
def get(self, section):
"""Get option.
@param section: section to fetch.
@return: option value.
"""
try:
return getattr(self, section)
except AttributeError as e:
raise OperationalError("Option %s is not found in "
"configuration, error: %s" %
(section, e))
if __name__ == "__main__":
conf = Config()
print conf.get("database").connect
print conf.get("database").sleep
print conf.get("database").test
執(zhí)行結(jié)果
mysql
False
True
目錄結(jié)構(gòu)
demo ? ? conf ? ? ? ? test.conf ? ? config.py
讀取配置文件&&簡單封裝
之前有做過把爬蟲數(shù)據(jù)寫到數(shù)據(jù)庫中的練習(xí),這次想把數(shù)據(jù)庫信息抽離到一個ini配置文件中,這樣做的好處在于可以在配置文件中添加多個數(shù)據(jù)庫,方便切換(另外配置文件也可以添加諸如郵箱、url等信息)
1.configparser模塊
python使用自帶的configparser模塊用來讀取配置文件,配置文件的形式類似windows中的ini文件
在使用前需要先安裝該模塊,使用pip安裝即可
2.configparser讀取文件的基本方法
(1)新建一個config.ini文件,如下

(2)新建一個readconfig.py文件,讀取配置文件的信息
import configparser
cf = configparser.ConfigParser()
cf.read("E:\Crawler\config.ini") # 讀取配置文件,如果寫文件的絕對路徑,就可以不用os模塊
secs = cf.sections() # 獲取文件中所有的section(一個配置文件中可以有多個配置,如數(shù)據(jù)庫相關(guān)的配置,郵箱相關(guān)的配置, 每個section由[]包裹,即[section]),并以列表的形式返回
print(secs)
options = cf.options("Mysql-Database") # 獲取某個section名為Mysql-Database所對應(yīng)的鍵
print(options)
items = cf.items("Mysql-Database") # 獲取section名為Mysql-Database所對應(yīng)的全部鍵值對
print(items)
host = cf.get("Mysql-Database", "host") # 獲取[Mysql-Database]中host對應(yīng)的值
print(host)上述代碼運行結(jié)果如下,可以和config.ini進(jìn)行對比

3.引入os模塊,使用相對目錄讀取配置文件
工程目錄如下:

readconfig.py:
import configparser
import os
root_dir = os.path.dirname(os.path.abspath('.')) # 獲取當(dāng)前文件所在目錄的上一級目錄,即項目所在目錄E:\Crawler
cf = configparser.ConfigParser()
cf.read(root_dir+"/config.ini") # 拼接得到config.ini文件的路徑,直接使用
secs = cf.sections() # 獲取文件中所有的section(一個配置文件中可以有多個配置,如數(shù)據(jù)庫相關(guān)的配置,郵箱相關(guān)的配置,每個section由[]包裹,即[section]),并以列表的形式返回
print(secs)
options = cf.options("Mysql-Database") # 獲取某個section名為Mysql-Database所對應(yīng)的鍵
print(options)
items = cf.items("Mysql-Database") # 獲取section名為Mysql-Database所對應(yīng)的全部鍵值對
print(items)
host = cf.get("Mysql-Database", "host") # 獲取[Mysql-Database]中host對應(yīng)的值
print(host)或者使用os.path.join()進(jìn)行拼接
import configparser
import os
root_dir = os.path.dirname(os.path.abspath('.')) # 獲取當(dāng)前文件所在目錄的上一級目錄,即項目所在目錄E:\Crawler
configpath = os.path.join(root_dir, "config.ini")
cf = configparser.ConfigParser()
cf.read(configpath) # 讀取配置文件
secs = cf.sections() # 獲取文件中所有的section(一個配置文件中可以有多個配置,如數(shù)據(jù)庫相關(guān)的配置,郵箱相關(guān)的配置,每個section由[]包裹,即[section]),并以列表的形式返回
print(secs)
options = cf.options("Mysql-Database") # 獲取某個section名為Mysql-Database所對應(yīng)的鍵
print(options)
items = cf.items("Mysql-Database") # 獲取section名為Mysql-Database所對應(yīng)的全部鍵值對
print(items)
host = cf.get("Mysql-Database", "host") # 獲取[Mysql-Database]中host對應(yīng)的值
print(host)4.通過讀取配置文件
重新寫一下之前的requests+正則表達(dá)式爬取貓眼電影的例子
把讀取配置文件readconfig.py和操作數(shù)據(jù)庫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):
"""連接數(shù)據(jù)庫"""
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):
"""執(zhí)行操作數(shù)據(jù)的相關(guān)sql"""
self.conn_mysql()
self.cur.execute(sql, data)
self.conn.commit()
def search(self, sql):
"""執(zhí)行查詢sql"""
self.conn_mysql()
self.cur.execute(sql)
return self.cur.fetchall()
def close_mysql(self):
"""關(guān)閉數(shù)據(jù)庫連接"""
self.cur.close()
self.conn.close()
if __name__ == '__main__':
test = HandleMysql()
sql = "select * from maoyan_movie"
for i in test.search(sql):
print(i)最后的運行文件,調(diào)用前面的方法
# 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>' # 匹配分?jǐn)?shù)的整數(shù)位
r'.*?<i.*?"fraction">(.*?)</i>.*?</dd>', re.S) # 匹配分?jǐn)?shù)小數(shù)位
m = pattern.findall(html)
for i in m: # 因為匹配到的所有結(jié)果會以列表形式返回,每部電影信息以元組形式保存,所以可以迭代處理每組電影信息
ranking = i[0] # 提取一組電影信息中的排名
movie = i[1] # 提取一組電影信息中的名稱
release_time = i[2] # 提取一組電影信息中的上映時間
score = i[3] + i[4] # 提取一組電影信息中的分?jǐn)?shù),這里把分?jǐn)?shù)的整數(shù)部分和小數(shù)部分拼在一起
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('導(dǎo)入成功')
except:
print('導(dǎo)入失敗')
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參數(shù)是指正則匹配并處理后的列表數(shù)據(jù)(是一個大列表,包含所有電影信息,每個電影信息都存在各自的一個列表中;
對大列表進(jìn)行迭代,提取每組電影信息,這樣提取到的每組電影信息都是一個小列表,然后就可以把每組電影信息寫入數(shù)據(jù)庫了)"""
movie = i # 每組電影信息,這里可以看做是準(zhǔn)備插入數(shù)據(jù)庫的每組電影數(shù)據(jù)
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()以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python程序員鮮為人知但你應(yīng)該知道的17個問題
這篇文章主要介紹了Python程序員代碼編寫時應(yīng)該避免的17個“坑”,也可以說成Python程序員代碼編寫時應(yīng)該避免的17個問題,需要的朋友可以參考下2014-06-06
Python中處理字符串之endswith()方法的使用簡介
這篇文章主要介紹了Python中處理字符串之endswith()方法的使用,是Python入門中的基礎(chǔ)知識,需要的朋友可以參考下2015-05-05
使用pytorch搭建AlexNet操作(微調(diào)預(yù)訓(xùn)練模型及手動搭建)
今天小編就為大家分享一篇使用pytorch搭建AlexNet操作(微調(diào)預(yù)訓(xùn)練模型及手動搭建),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-01-01
python?pandas分割DataFrame中的字符串及元組的方法實現(xiàn)
本文主要介紹了python?pandas分割DataFrame中的字符串及元組的方法實現(xiàn),主要介紹了3種方法,具有一定的參考價值,感興趣的可以了解一下2022-03-03
Django model.py表單設(shè)置默認(rèn)值允許為空的操作
這篇文章主要介紹了Django model.py表單設(shè)置默認(rèn)值允許為空的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-05-05

