<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
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
執行結果
mysql
False
True
目錄結構
demo conf test.conf config.py
之前有做過把爬蟲資料寫到資料庫中的練習,這次想把資料庫資訊抽離到一個ini組態檔中,這樣做的好處在於可以在組態檔中新增多個資料庫,方便切換(另外組態檔也可以新增諸如郵箱、url等資訊)
python使用自帶的configparser模組用來讀取組態檔,組態檔的形式類似windows中的ini檔案
在使用前需要先安裝該模組,使用pip安裝即可
(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進行對比
工程目錄如下:
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)
重新寫一下之前的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()
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45