1. 程式人生 > >[Python] [爬蟲] 10.批量政府網站的招投標、中標資訊爬取和推送的自動化爬蟲——排程引擎

[Python] [爬蟲] 10.批量政府網站的招投標、中標資訊爬取和推送的自動化爬蟲——排程引擎

目錄

1.Intro

2.Source


1.Intro

檔名:scheduleEngine.py

模組名:排程引擎

引用庫:

random time gc os
sys datetime retry  

自定義引用檔案:authentication、proxyPool、configManager、pageDownloader、dateDisposer、spiderLog、dataPusher、dataPusher_HTML、Console_Color、log_record

功能:構造代理引擎、獨立代理引擎、驗證引擎、網頁爬取引擎、資料推送引擎,然後統一排程,完成推送。

注:寫的有點冗餘,目前懶得改了,有空就改。

 

2.Source

#!/usr/bin/env Python
# -*- coding: utf-8 -*-
'''
# Author  : YSW
# Time    : 2018/6/7 15:47
# File    : scheduleEngine.py
# Version : 2.0
# Describe: 排程引擎
# Update  :
        1.重構了排程引擎,可以實現全自動化爬取和推送。
'''
######## Import ########
import random
import time
import gc  # 記憶體釋放
import os
import sys
import authentication  # 驗證模組
import proxyPool  # 代理池
import configManager  # 配置管理器
import pageDownloader  # 網頁下載器
import dataDisposer  # 資料處理器
import spiderLog  # 爬蟲日誌
import dataPusher  # 資料推送
import dataPush_HTML
import datetime
from retry import retry
from Lib import Console_Color
import log_record

######## Global Parameters ########
# 動態請求報頭
HEADERS = {
    "User-Agent": random.choice(configManager.headers)
}
# URL 列表
URL_LIST = configManager.urlData
URL_LIST_ZB = configManager.urlData_ZB
# 資料庫引數
DATABASE_PARAM = configManager.dataBaseParams
# 表的標題名
TABLE_TITLE = configManager.excel_table_title

# 全域性邏輯控制器
LOGIC_RESPONSE = False
LOGIC_EXECUTE = False
LOGIC_DB_DISPOSE = False
LOGIC_DATA_PUSH = False
LOGIC_PUSH_DONE = False

# 有效的 URL
VALID_URL = []
# 有效的 URL 和對應代理
VALID_URL_PROXY = {}
# 關鍵詞列表
KEY_WORD = []

# 獲取當前檔名
CURRENT_PY = os.path.basename(sys.argv[0]).split(".")[0]
# 建立日誌物件
LOG = spiderLog.SpiderLog(CURRENT_PY)
# 資料庫
TENDER_TABLE = dataDisposer.DataOperate.dataOperate()

# 獲取當前時間
DATE = dataDisposer.current_time()
TODAY_TIME = datetime.datetime(DATE.year, DATE.month, DATE.day, 0, 0, 0)
LOG_TIME = dataDisposer.current_time()

######## Engine Function ########

def proxy_engine(proxyOP):
    '''
    代理引擎
    :return: 返回代理 IP 字典,包含 ip、protocol、port
    '''
    LOG.info("[*] 開始執行代理引擎")
    try:
        LOG.info("[+] 獲取代理")
        proxyDict = proxyOP.auto_dispose()
        print("-" * 25)
        print("[+] 當前代理")
        print("| Protocol: {0}".format(str(proxyDict["protocol"])))
        print("| IP:       {0}".format(str(proxyDict["ip"])))
        print("| Port:     {0}".format(str(proxyDict["port"])))
        print("-" * 25)
        return proxyDict
    except Exception, e:
        LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
    finally:
        del proxyOP
        gc.collect()

@retry(tries=5, delay=2)
def independent_proxy_engine(url):
    '''
    獨立代理引擎,用於重新獲取單個異常網頁的代理
    :param url: 異常網頁的 url 連結
    :return:
    '''
    LOG.info("[+] 開始重新獲取代理")
    Console_Color.print_color(str="[*] 開始重新獲取代理", forecolor="洋紅")
    global VALID_URL_PROXY
    auth = authentication.Authentication(headers=HEADERS)
    proxyOP = proxyPool.IPOperator(headers=HEADERS)
    while True:
        proxyDict = proxy_engine(proxyOP)
        if auth.proxyVerify(url, proxyDict["protocol"], proxyDict["ip"], proxyDict["port"]):
            global VALID_URL_PROXY
            VALID_URL_PROXY[url] = proxyDict
            break

@retry(tries=5, delay=2)
def authentication_engine():
    '''
    驗證引擎
    :param proxyDict: 代理 IP 字典
    :return: 通過驗證後,賦值給響應邏輯器LOGIC_RESPONSE
    '''
    LOG.info("[*] 開始執行驗證引擎")
    auth = authentication.Authentication(headers=HEADERS)
    # 避免每次建立物件都開闢塊記憶體,呼叫四個程序池,特別佔記憶體
    proxyOP = proxyPool.IPOperator(headers=HEADERS)
    global VALID_URL
    try:
        #### 驗證 HTTP ####
        # 遍歷 url 列表進行 http 驗證請求,將有效的 url 儲存在 VALID_URL 中
        LOG.info("[+] 驗證 HTTP")  # 寫入日誌
        for url in URL_LIST.values():
            if auth.httpCodeVerify(url):
                VALID_URL.append(url)

        # 遍歷新加入的 url 列表
        for url_zb in URL_LIST_ZB.values():
            if auth.httpCodeVerify(url_zb):
                VALID_URL.append(url_zb)

        # 遍歷有效的 URL
        print("-" * 40)
        print("[+] 有效的 URL({0})".format(len(VALID_URL)))
        for valid_url in VALID_URL:
            print(str(valid_url))
        print("-" * 40)
    except Exception, e:
        LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌

    try:
        #### 驗證代理 ####
        # 遍歷有效的 url 列表
        LOG.info("[+] 驗證代理")  # 寫入日誌
        for url in VALID_URL:
            # 迴圈取出代理進行代理驗證,將有效的代理與對應的 url 儲存在字典中
            while True:
                proxyDict = proxy_engine(proxyOP)
                if auth.proxyVerify(url, proxyDict["protocol"], proxyDict["ip"], proxyDict["port"]):
                    global VALID_URL_PROXY
                    VALID_URL_PROXY[url] = proxyDict
                    break
                # 每進行一次 url 的代理驗證,釋放一次記憶體
                gc.collect()

        # 遍歷 VALID_URL_PROXY 字典
        print("-" * 40)
        print("[+] 有效網址和代理")
        for valid_url in VALID_URL_PROXY:
            protocol = VALID_URL_PROXY[valid_url]['protocol']
            ip = VALID_URL_PROXY[valid_url]['ip']
            port = VALID_URL_PROXY[valid_url]['port']
            print("{0}--({1}:{2}:{3})".format(valid_url, protocol, ip, port))
        print("-" * 40)

        # 儲存完成,賦值全域性變數
        global LOGIC_RESPONSE
        LOGIC_RESPONSE = True
    except Exception, e:
        LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌

    try:
        #### 驗證資料庫 ####
        LOG.info("[+] 驗證資料庫")
        if LOGIC_RESPONSE:
            global LOGIC_EXECUTE
            LOGIC_EXECUTE = auth.dataBaseVerify(DATABASE_PARAM)
    except Exception, e:
        LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌

    LOG.info("[+] 清理記憶體")
    # 刪除 auth 和 proxyOP 物件
    del auth, proxyOP
    # 清理記憶體
    gc.collect()

TRY_NUM_ynsggzxxt_gc = 1
TRY_NUM_ynsggzxxt_zf = 1
TRY_NUM_ynsggzzw_gc = 1
TRY_NUM_kmsgg_zf = 1
TRY_NUM_kmsgg_gc = 1
TRY_NUM_ynszfcgw = 1
TRY_NUM_ynsggzxxt_gc_zb = 1
TRY_NUM_ynsggzxxt_zf_zb = 1
TRY_NUM_ynsggzzw_gc_zb = 1
TRY_NUM_ynsggzzw_zf_zb = 1
TRY_NUM_kmsgg_gc_zb = 1
TRY_NUM_kmsgg_zf_zb = 1
TRY_NUM_kmsgg_gc_by = 1
TRY_NUM_kmsgg_zf_by = 1
TRY_NUM_ynszfcgw_cg = 1

def page_engine():
    '''
    網頁引擎
    '''
    LOG.info("[*] 開始執行網頁引擎")
    downloader = pageDownloader.DownLoader(HEADERS)

    #### 招投標資訊 ####

    def ynsggzxxt_gc():
        global TRY_NUM_ynsggzxxt_gc
        try:
            downloader.downloader_ynsggzxxt(
                URL_LIST['雲南省公共資源交易中心電子服務系統_工程建設'],
                VALID_URL_PROXY[URL_LIST['雲南省公共資源交易中心電子服務系統_工程建設']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_ynsggzxxt_gc))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_ynsggzxxt_gc += 1
            if TRY_NUM_ynsggzxxt_gc > 5:
                TRY_NUM_ynsggzxxt_gc = 1
                independent_proxy_engine(URL_LIST['雲南省公共資源交易中心電子服務系統_工程建設'])
            ynsggzxxt_gc()

    def ynsggzxxt_zf():
        global TRY_NUM_ynsggzxxt_zf
        try:
            downloader.downloader_ynsggzxxt_zf(
                URL_LIST['雲南省公共資源交易中心電子服務系統_政府採購'],
                VALID_URL_PROXY[URL_LIST['雲南省公共資源交易中心電子服務系統_政府採購']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_ynsggzxxt_zf))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_ynsggzxxt_zf += 1
            if TRY_NUM_ynsggzxxt_zf > 5:
                TRY_NUM_ynsggzxxt_zf = 1
                independent_proxy_engine(URL_LIST['雲南省公共資源交易中心電子服務系統_政府採購'])
            ynsggzxxt_zf()

    def ynsggzzw_gc():
        global TRY_NUM_ynsggzzw_gc
        try:
            downloader.downloader_ynsggzzw(
                URL_LIST['雲南省公共資源交易中心網_工程建設'],
                VALID_URL_PROXY[URL_LIST['雲南省公共資源交易中心網_工程建設']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_ynsggzzw_gc))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_ynsggzzw_gc += 1
            if TRY_NUM_ynsggzzw_gc > 5:
                TRY_NUM_ynsggzzw_gc = 1
                independent_proxy_engine(URL_LIST['雲南省公共資源交易中心網_工程建設'])
            ynsggzzw_gc()

    def kmsgg_zf():
        global TRY_NUM_kmsgg_zf
        try:
            downloader.downloader_kmsgg(
                URL_LIST['昆明市公共資源交易中心網_政府採購'],
                VALID_URL_PROXY[URL_LIST['昆明市公共資源交易中心網_政府採購']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_kmsgg_zf))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_kmsgg_zf += 1
            if TRY_NUM_kmsgg_zf > 5:
                TRY_NUM_kmsgg_zf = 1
                independent_proxy_engine(URL_LIST['昆明市公共資源交易中心網_政府採購'])
            kmsgg_zf()

    def kmsgg_gc():
        global TRY_NUM_kmsgg_gc
        try:
            downloader.downloader_kmsgg_gc(
                URL_LIST['昆明市公共資源交易中心網_工程建設'],
                VALID_URL_PROXY[URL_LIST['昆明市公共資源交易中心網_工程建設']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_kmsgg_gc))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_kmsgg_gc += 1
            if TRY_NUM_kmsgg_gc > 5:
                TRY_NUM_kmsgg_gc = 1
                independent_proxy_engine(URL_LIST['昆明市公共資源交易中心網_工程建設'])
            kmsgg_gc()

    def ynszfcgw():
        global TRY_NUM_ynszfcgw
        try:
            downloader.downloader_ynszfcgw(
                URL_LIST['雲南省政府採購網'],
                VALID_URL_PROXY[URL_LIST['雲南省政府採購網']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_ynszfcgw))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_ynszfcgw += 1
            if TRY_NUM_ynszfcgw > 5:
                TRY_NUM_ynszfcgw = 1
                independent_proxy_engine(URL_LIST['雲南省政府採購網'])
            ynszfcgw()


    #### 中標資訊 ####
    def ynsggzxxt_gc_zb():
        global TRY_NUM_ynsggzxxt_gc_zb
        try:
            downloader.downloader_ynsggzxxt_gc_zb(
                URL_LIST_ZB['雲南省公共資源交易資訊網_工程建設_中標公告'],
                VALID_URL_PROXY[URL_LIST_ZB['雲南省公共資源交易資訊網_工程建設_中標公告']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_ynsggzxxt_gc_zb))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_ynsggzxxt_gc_zb += 1
            if TRY_NUM_ynsggzxxt_gc_zb > 5:
                TRY_NUM_ynsggzxxt_gc_zb = 1
                independent_proxy_engine(URL_LIST['雲南省公共資源交易資訊網_工程建設_中標公告'])
            ynsggzxxt_gc_zb()

    def ynsggzxxt_zf_zb():
        global TRY_NUM_ynsggzxxt_zf_zb
        try:
            downloader.downloader_ynsggzxxt_zf_zb(
                URL_LIST_ZB['雲南省公共資源交易資訊網_政府採購_中標結果'],
                VALID_URL_PROXY[URL_LIST_ZB['雲南省公共資源交易資訊網_政府採購_中標結果']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_ynsggzxxt_zf_zb))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_ynsggzxxt_zf_zb += 1
            if TRY_NUM_ynsggzxxt_zf_zb > 5:
                TRY_NUM_ynsggzxxt_zf_zb = 1
                independent_proxy_engine(URL_LIST['雲南省公共資源交易資訊網_政府採購_中標結果'])
            ynsggzxxt_zf_zb()

    def ynsggzzw_gc_zb():
        global TRY_NUM_ynsggzzw_gc_zb
        try:
            downloader.downloader_ynsggzzw_gc_zb(
                URL_LIST_ZB['雲南省公共資源交易中心_工程建設_中標結果'],
                VALID_URL_PROXY[URL_LIST_ZB['雲南省公共資源交易中心_工程建設_中標結果']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_ynsggzzw_gc_zb))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_ynsggzzw_gc_zb += 1
            if TRY_NUM_ynsggzzw_gc_zb > 5:
                TRY_NUM_ynsggzzw_gc_zb = 1
                independent_proxy_engine(URL_LIST['雲南省公共資源交易中心_工程建設_中標結果'])
            ynsggzzw_gc_zb()

    def ynsggzzw_zf_zb():
        global TRY_NUM_ynsggzzw_zf_zb
        try:
            downloader.downloader_ynsggzzw_zf_zb(
                URL_LIST_ZB['雲南省公共資源交易中心_政府採購_結果公示'],
                VALID_URL_PROXY[URL_LIST_ZB['雲南省公共資源交易中心_政府採購_結果公示']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_ynsggzzw_zf_zb))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_ynsggzzw_zf_zb += 1
            if TRY_NUM_ynsggzzw_zf_zb > 5:
                TRY_NUM_ynsggzzw_zf_zb = 1
                independent_proxy_engine(URL_LIST['雲南省公共資源交易中心_政府採購_結果公示'])
            ynsggzzw_zf_zb()

    def kmsgg_gc_zb():
        global TRY_NUM_kmsgg_gc_zb
        try:
            downloader.downloader_kmsgg_gc_zb(
                URL_LIST_ZB['昆明市公共資源交易平臺公共服務系統_工程建設_中標結果公示'],
                VALID_URL_PROXY[URL_LIST_ZB['昆明市公共資源交易平臺公共服務系統_工程建設_中標結果公示']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_kmsgg_gc_zb))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_kmsgg_gc_zb += 1
            if TRY_NUM_kmsgg_gc_zb > 5:
                TRY_NUM_kmsgg_gc_zb = 1
                independent_proxy_engine(URL_LIST['昆明市公共資源交易平臺公共服務系統_工程建設_中標結果公示'])
            kmsgg_gc_zb()

    def kmsgg_zf_zb():
        global TRY_NUM_kmsgg_zf_zb
        try:
            downloader.downloader_kmsgg_zf_zb(
                URL_LIST_ZB['昆明市公共資源交易平臺公共服務系統_政府採購_結果公示'],
                VALID_URL_PROXY[URL_LIST_ZB['昆明市公共資源交易平臺公共服務系統_政府採購_結果公示']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_kmsgg_zf_zb))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_kmsgg_zf_zb += 1
            if TRY_NUM_kmsgg_zf_zb > 5:
                TRY_NUM_kmsgg_zf_zb = 1
                independent_proxy_engine(URL_LIST['昆明市公共資源交易平臺公共服務系統_政府採購_結果公示'])
            kmsgg_zf_zb()

    def kmsgg_gc_by():
        global TRY_NUM_kmsgg_gc_by
        try:
            downloader.downloader_kmsgg_gc_by(
                URL_LIST_ZB['昆明市公共資源交易平臺公共服務系統_工程建設_補遺通知'],
                VALID_URL_PROXY[URL_LIST_ZB['昆明市公共資源交易平臺公共服務系統_工程建設_補遺通知']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_kmsgg_gc_by))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_kmsgg_gc_by += 1
            if TRY_NUM_kmsgg_gc_by > 5:
                TRY_NUM_kmsgg_gc_by = 1
                independent_proxy_engine(URL_LIST['昆明市公共資源交易平臺公共服務系統_工程建設_補遺通知'])
            kmsgg_gc_by()

    def kmsgg_zf_by():
        global TRY_NUM_kmsgg_zf_by
        try:
            downloader.downloader_kmsgg_zf_by(
                URL_LIST_ZB['昆明市公共資源交易平臺公共服務系統_政府採購_補遺通知'],
                VALID_URL_PROXY[URL_LIST_ZB['昆明市公共資源交易平臺公共服務系統_政府採購_補遺通知']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_kmsgg_zf_by))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_kmsgg_zf_by += 1
            if TRY_NUM_kmsgg_zf_by > 5:
                TRY_NUM_kmsgg_zf_by = 1
                independent_proxy_engine(URL_LIST['昆明市公共資源交易平臺公共服務系統_政府採購_補遺通知'])
            kmsgg_zf_by()

    def ynszfcgw_cg():
        global TRY_NUM_ynszfcgw_cg
        try:
            downloader.downloader_ynszfcgw_cg(
                URL_LIST_ZB['雲南省政府採購網_採購結果'],
                VALID_URL_PROXY[URL_LIST_ZB['雲南省政府採購網_採購結果']])
        except Exception, e:
            LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
            LOG.error("[-] {0}".format(str("Trying times: {0}".format(TRY_NUM_ynszfcgw_cg))))  # 寫入日誌
            time.sleep(10)
            TRY_NUM_ynszfcgw_cg += 1
            if TRY_NUM_ynszfcgw_cg > 5:
                TRY_NUM_ynszfcgw_cg = 1
                independent_proxy_engine(URL_LIST['雲南省政府採購網_採購結果'])
            ynszfcgw_cg()


    global LOGIC_DB_DISPOSE
    LOG.info("[+] 抓取資料")
    print("[*] 開始抓取招投標資訊..")
    #### 招投標資訊 ####
    ynsggzxxt_gc()
    ynsggzxxt_zf()
    ynsggzzw_gc()
    kmsgg_zf()
    kmsgg_gc()
    ynszfcgw()

    print("[*] 開始抓取中標資訊..")
    #### 中標資訊 ####
    ynsggzxxt_gc_zb()
    ynsggzxxt_zf_zb()
    ynsggzzw_gc_zb()
    ynsggzzw_zf_zb()
    kmsgg_gc_zb()
    kmsgg_zf_zb()
    kmsgg_gc_by()
    kmsgg_zf_by()
    ynszfcgw_cg()

    LOG.info("[+] 抓取完成")
    # del downloader
    gc.collect()
    LOGIC_DB_DISPOSE = True

def db_engine():
    '''
    資料庫引擎
    '''
    LOG.info("[*] 開始執行資料庫引擎")
    # 建立資料處理物件
    #### 招投標資料 ####
    ynsggzxxt = dataDisposer.DataStore('ynsggzxxt')
    ynsggzzw = dataDisposer.DataStore('ynsggzzw')
    kmsgg = dataDisposer.DataStore('kmsgg')
    kmsgg_gc = dataDisposer.DataStore('kmsgg_gc')
    ynsggzxxt_zf = dataDisposer.DataStore('ynsggzxxt_zf')
    ynszfcgw = dataDisposer.DataStore('ynszfcgw')

    #### 中標資料 ####
    ynsggzxxt_gc_zb = dataDisposer.DataStore('ynsggzxxt_gc_zb')
    ynsggzxxt_zf_zb = dataDisposer.DataStore('ynsggzxxt_zf_zb')

    ynsggzzw_gc_zb = dataDisposer.DataStore('ynsggzzw_gc_zb')
    ynsggzzw_zf_zb = dataDisposer.DataStore('ynsggzzw_zf_zb')

    kmsgg_gc_zb = dataDisposer.DataStore('kmsgg_gc_zb')
    kmsgg_zf_zb = dataDisposer.DataStore('kmsgg_zf_zb')
    kmsgg_gc_by = dataDisposer.DataStore('kmsgg_gc_by')
    kmsgg_zf_by = dataDisposer.DataStore('kmsgg_zf_by')

    ynszfcgw_cg = dataDisposer.DataStore('ynszfcgw_cg')

    global LOGIC_DATA_PUSH
    try:
        LOG.info("[+] 資料庫處理中")
        #### 資料操作 ####

        ## 招投標資料 ##
        ## 雲南省公共資源交易中心電子服務系統
        ynsggzxxt.clean_data(['公告標題', '專案編號'])  # 資料清洗(去重)
        ynsggzxxt.update_date_by_time('截止時間')  # 資料更新(時間)
        ynsggzxxt.delete_none_data()

        ## 雲南省公共資源交易中心網(舊)
        ynsggzzw.clean_data(['公告標題', '專案編號'])   # 資料清洗(去重)
        ynsggzzw.delete_none_data()

        ## 昆明市公共資源交易中心網
        kmsgg.clean_data(['編號', '工程名稱'])  # 資料清洗(去重)
        kmsgg.update_date_by_time("結束時間")  # 資料更新(時間)
        kmsgg.delete_none_data()

        ## 昆明市公共資源交易中心網_工程
        kmsgg_gc.clean_data(['編號', '工程名稱'])  # 資料清洗(去重)
        kmsgg_gc.update_date_by_time("結束時間")  # 資料更新(時間)
        kmsgg_gc.delete_none_data()

        ## 雲南省公共資源交易中心電子服務系統_政府
        ynsggzxxt_zf.clean_data(['公告標題', '專案編號'])  # 資料清洗(去重)
        ynsggzxxt_zf.update_date_by_time('截止時間')  # 資料更新(時間)
        ynsggzxxt_zf.delete_none_data()

        ## 雲南省政府採購網
        ynszfcgw.clean_data(['編號', '工程名稱'])  # 資料清洗(去重)
        ynszfcgw.delete_none_data()

        ## 中標資料 ##
        # 雲南省公共資源交易資訊網_工程建設_中標公告
        ynsggzxxt_gc_zb.clean_data(['專案名稱', '釋出時間'])
        ynsggzxxt_gc_zb.delete_none_data()
        # 雲南省公共資源交易資訊網_政府採購_中標結果
        ynsggzxxt_zf_zb.clean_data(['專案名稱', '釋出時間'])
        ynsggzxxt_zf_zb.delete_none_data()

        # 雲南省公共資源交易中心_工程建設_中標結果
        ynsggzzw_gc_zb.clean_data(['公告標題', '釋出時間'])
        ynsggzzw_gc_zb.delete_none_data()
        # 雲南省公共資源交易中心_政府採購_結果公示
        ynsggzzw_zf_zb.clean_data(['公告標題', '釋出時間'])
        ynsggzzw_zf_zb.delete_none_data()

        # 昆明市公共資源交易平臺公共服務系統_工程建設_中標結果公示
        kmsgg_gc_zb.clean_data(['編號', '工程名稱'])
        kmsgg_gc_zb.delete_none_data()
        # 昆明市公共資源交易平臺公共服務系統_政府採購_結果公示
        kmsgg_zf_zb.clean_data(['編號', '工程名稱'])
        kmsgg_zf_zb.delete_none_data()
        # 昆明市公共資源交易平臺公共服務系統_工程建設_補遺通知
        kmsgg_gc_by.clean_data(['編號', '工程名稱'])
        kmsgg_gc_by.delete_none_data()
        # 昆明市公共資源交易平臺公共服務系統_政府採購_補遺通知
        kmsgg_zf_by.clean_data(['編號', '工程名稱'])
        kmsgg_zf_by.delete_none_data()

        # 雲南省政府採購網_採購結果
        ynszfcgw_cg.clean_data(['編號', '工程名稱'])
        ynszfcgw_cg.delete_none_data()

        ##################
        LOG.info("[+] 資料庫處理完成")
        LOGIC_DATA_PUSH = True
    except Exception, e:
        LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
        LOGIC_DATA_PUSH = False
    finally:
        # 刪除物件,釋放記憶體
        del ynsggzxxt, ynsggzzw, kmsgg #, ynsggzxxt_zb, ynsggzzw_zb, ynstz_zb, kmsgg_zb
        gc.collect()

def data_push_engine():
    '''
    資料推送引擎
    :return:
    '''
    LOG.info("[*] 開始執行資料推送引擎")
    #### 初始化資料寫入模組 ####
    writer = dataPusher.DataWrite()
    html_push = dataPush_HTML.HTML_Content()

    # 雲南省公共資源交易中心電子服務系統 'ynsggzxxt'
    # 雲南省公共資源交易中心電子服務系統_政府採購 'ynsggzxxt_zf'
    # 雲南省公共資源交易中心網 'ynsggzzw'
    # 昆明市公共資源交易中心網 'kmsgg'
    # 昆明市公共資源交易中心網_工程建設 'kmsgg_gc'
    # 雲南省政府採購網 'ynszfcgw'
    #  table_name = ['ynsggzxxt', 'ynsggzzw', 'kmsgg', 'kmsgg_gc', 'ynsggzxxt_zf', 'ynszfcgw', ] #'ynsggzxxt_zb', 'ynsggzzw_zb', 'ynstz_zb', 'kmsgg_zb']
    list_file_path = []

    try:
        #----------- 舊方法 -----------#
        # # 遍歷表
        # for table in table_name:
        #     list_data = get_data(table)
        #     header_data = configManager.excel_header_data[table]
        #     # header_data_zb = configManager.excel_header_data_zb[table]
        #
        #     # 讀取關鍵詞檔案並生成關鍵字列表
        #     with open(r".\keyword_file\keyword.txt", 'r') as f:
        #         line = f.read()
        #         if line not in KEY_WORD:
        #             KEY_WORD.append(line)
        #     key_word = str(KEY_WORD[0]).split('\n')
        #
        #     # 篩選關鍵詞資訊
        #     list_data_parse = []
        #     for data in list_data:
        #         for key in key_word:
        #             # 獲取每張表對應的標題欄位並判斷是否包含關鍵詞資訊
        #             if key in data[TABLE_TITLE[table]] and data not in list_data_parse:
        #                 list_data_parse.append(data)
        #
        #     # 判斷當天資料是否為空
        #     # 寫入兩個 excel 文字(招投標)
        #     if len(list_data) != 0:
        #         file_path = writer.excel_write(
        #             excel_sheet_name=configManager.excel_data_name[table],
        #             excel_head_data=header_data,
        #             excel_data=list_data,
        #             logic_file_type=0
        #         )
        #
        #     if len(list_data_parse) != 0:
        #         file_path_parse = writer.excel_write_parse(
        #             excel_sheet_name=configManager.excel_data_name[table],
        #             excel_head_data=header_data,
        #             excel_data=list_data_parse,
        #             logic_file_type=1
        #         )
        #
        #     # 寫入兩個 excel 文字(中標)
        #     # file_path_zb = writer.excel_write(excel_sheet_name=configManager.excel_data_name_zb[table], excel_head_data=header_data_zb, excel_data=dict_data, logic_file_type=2)
        #     # file_path_parse_zb = writer.excel_write(excel_sheet_name=configManager.excel_data_name_zb[table], excel_head_data=header_data_zb, excel_data=dict_data_parse, logic_file_type=3)
        # ---------------------------#


        LOG.info("[+] 正在寫入檔案...")
        file_path = html_push.html_write(
            title="招投標資訊",
            name="今日份的招投標檔案",
            dict_html_data_name=configManager.ztb_data_name,
            logic_file_type=0
        )

        file_path_parse = html_push.html_write_keywords(
            title="招投標資訊",
            name="今日份的招投標檔案(關鍵詞篩選)",
            dict_html_data_name=configManager.ztb_data_name,
            logic_file_type=1
        )

        file_path_zb = html_push.html_write(
            title="中標資訊",
            name="今日份的中標檔案",
            dict_html_data_name=configManager.zb_data_name,
            logic_file_type=2
        )

        file_path_parse_zb = html_push.html_write_keywords(
            title="中標資訊",
            name="今日份的中標檔案(關鍵詞篩選)",
            dict_html_data_name=configManager.zb_data_name,
            logic_file_type=3
        )

        # 遍歷路徑新增到路徑列表中
        if file_path != "":
            if file_path not in list_file_path:
                list_file_path.append(file_path)

        if file_path_parse != "":
            if file_path_parse not in list_file_path:
                list_file_path.append(file_path_parse)

        if file_path_zb != "":
            if file_path_zb not in list_file_path:
                list_file_path.append(file_path_zb)

        if file_path_parse_zb != "":
            if file_path_parse_zb not in list_file_path:
                list_file_path.append(file_path_parse_zb)

        LOG.info("[+] 寫入完成")
    except Exception, e:
        LOG.error("[-] {0}".format(str(e.message)))  # 寫入日誌
    finally:
        # 刪除物件,釋放記憶體
        del writer
        gc.collect()

    #### 初始化資料推送模組 ####
    LOG.info("[+] 正在推送資料...")
    pusher = dataPusher.DataSend()
    try:
        if len(list_file_path) != 0:
            content = """
            自動化爬蟲
            版本:5.1
            當前時間:{0}
            開發語言:Python 2.7
            資料庫:MongoDB 3.6.5
            平臺:Windows Server 2012 Data Center
			版本更新:
				1.優化了爬取演算法,提高了推送成功率,出現斷電的情況會進行補充推送。
					
			如有任何問題和建議,請聯絡開發者:
[email protected]
""".format(dataDisposer.current_time()) else: content = """ 爬蟲提示:今天沒有推送的資料哦 自動化爬蟲 版本:5.1 當前時間:{0} 開發語言:Python 2.7 資料庫:MongoDB 3.6.5 平臺:Windows Server 2012 Data Center 版本更新: 1.優化了爬取演算法,提高了推送成功率,出現斷電的情況會進行補充推送。 如有任何問題和建議,請聯絡開發者:
[email protected]
""".format(dataDisposer.current_time()) global LOGIC_PUSH_DONE # 將附件新增到文字中 if pusher.send_mail(content, list_file_path): LOGIC_PUSH_DONE = True else: LOGIC_PUSH_DONE = False LOG.info("[+] 推送完成") log_record.log_recorder(LOG_TIME, "執行成功") except Exception, e: LOG.error("[-] {0}".format(str(e.message))) # 寫入日誌 log_record.log_recorder(LOG_TIME, "執行失敗") finally: # 刪除物件,釋放記憶體 del pusher gc.collect() def get_data(table_name): ''' 資料獲取函式 :param table_name: 表名 :return: 返回資料列表 ''' tenderTable = TENDER_TABLE[table_name] # 獲取今日資料 list_data = list(tenderTable.find( { '釋出時間': {"$gte": TODAY_TIME}, '推送': False }) ) tenderTable.update( {'推送': False}, {'$set': {'推送': True}}, multi=True, upsert=True ) return list_data def current_time_parse(): ''' 獲取當前時間,返回小時和分鐘 :return: 當前小時和分鐘 ''' current_date = dataDisposer.current_time() current_hour = current_date.hour current_minute = current_date.minute return current_hour, current_minute ######## Main Function ######## def main(): print("-" * 40) print("[*] 開始執行爬蟲程式") print("[+] 版本:5.1") print("-" * 40) time.sleep(2) # 驗證代理和網頁請求返回值 authentication_engine() # 如果驗證執行完畢,開始執行網頁引擎 if LOGIC_EXECUTE: page_engine() # 如果網頁引擎執行完畢,開始執行資料庫引擎 if LOGIC_DB_DISPOSE: db_engine() # 如果資料庫引擎執行完畢,開始執行資料推送引擎 if LOGIC_DATA_PUSH: data_push_engine() # 如果資料推送引擎執行完畢,則關閉整個引擎 if LOGIC_PUSH_DONE: print("[+] 爬蟲執行完成,引擎關閉") ######## Start Execute ######## if __name__ == "__main__": start = time.clock() main() end = time.clock() print ("[+] 執行消耗時長:{0}".format(end - start))