成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

利用Scrapy實(shí)現(xiàn)公司內(nèi)部門(mén)戶(hù)消息郵件通知

tuantuan / 2781人閱讀

摘要:一項(xiàng)目背景我本人所在公司是一個(gè)國(guó)有企業(yè),自建有較大的內(nèi)部網(wǎng)絡(luò)門(mén)戶(hù)群,幾乎所有部門(mén)發(fā)布各類(lèi)通知工作要求等消息都在門(mén)戶(hù)網(wǎng)站進(jìn)行。為了改變這種狀況,就想建立一個(gè)內(nèi)部網(wǎng)絡(luò)消息跟蹤通知系統(tǒng)。

一、項(xiàng)目背景

  我本人所在公司是一個(gè)國(guó)有企業(yè),自建有較大的內(nèi)部網(wǎng)絡(luò)門(mén)戶(hù)群,幾乎所有部門(mén)發(fā)布各類(lèi)通知、工作要求等消息都在門(mén)戶(hù)網(wǎng)站進(jìn)行。由于對(duì)應(yīng)的上級(jí)部門(mén)比較多,各類(lèi)通知通告、領(lǐng)導(dǎo)講話(huà)等內(nèi)容類(lèi)目繁多,要看一遍真需要花費(fèi)點(diǎn)時(shí)間。更重要的是有些會(huì)議通知等時(shí)效性比較強(qiáng)的消息一旦遺漏錯(cuò)過(guò)重要會(huì)議就比較麻煩。為了改變這種狀況,就想建立一個(gè)內(nèi)部網(wǎng)絡(luò)消息跟蹤、通知系統(tǒng)。

二、基本功能

  主要功能:系統(tǒng)功能比較簡(jiǎn)單,主要就是爬取內(nèi)部網(wǎng)絡(luò)固定的一些通知頁(yè)面,發(fā)現(xiàn)新的通知就向指定的人發(fā)送通知郵件。
  涉及到的功能點(diǎn):
  1.常規(guī)頁(yè)面請(qǐng)求
  2.post請(qǐng)求
  3.數(shù)據(jù)存儲(chǔ)
  4.識(shí)別新消息
  5.郵件通知
  6.定時(shí)啟動(dòng),循環(huán)運(yùn)行

三、詳細(xì)說(shuō)明 (一)文件結(jié)構(gòu)

  上圖顯示了完成狀態(tài)的文件結(jié)構(gòu),與新建的scrapy項(xiàng)目相比增加的文件有兩部分:
  一是spiders目錄下的6個(gè)爬蟲(chóng)文件,對(duì)應(yīng)了6個(gè)欄目,以后根據(jù)需要還會(huì)再增加;
  二是涉及定時(shí)啟動(dòng)、循環(huán)運(yùn)行功能的幾個(gè)文件,分別是commands文件夾、noticeStart.py、setup.py、autorun.bat

(二)各部分代碼 1. items.py
import scrapy

class JlshNoticeItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    noticeType = scrapy.Field()     #通知類(lèi)別
    noticeTitle = scrapy.Field()    #通知標(biāo)題
    noticeDate = scrapy.Field()     #通知日期
    noticeUrl = scrapy.Field()      #通知URL
    noticeContent = scrapy.Field()  #通知內(nèi)容
2. spider

  篇幅關(guān)系,這里只拿一個(gè)爬蟲(chóng)做例子,其它的爬蟲(chóng)只是名稱(chēng)和start_url不同,下面代碼盡量做到逐句注釋。

代碼
from scrapy import Request
from scrapy import FormRequest
from scrapy.spiders import Spider
from jlsh_notice.items import JlshNoticeItem
from jlsh_notice.settings import DOWNLOAD_DELAY
from scrapy.crawler import CrawlerProcess
from datetime import date
import requests
import lxml
import random
import re
#=======================================================
class jlsh_notice_spider_gongsitongzhi(Spider):
    #爬蟲(chóng)名稱(chēng)
    name = "jlsh_gongsitongzhi"
    
    start_urls = [
        "http://www.jlsh.petrochina/sites/jlsh/news/inform/Pages/default.aspx", #公司通知
    ]
#=======================================================
    #處理函數(shù)
    def parse(self, response):
        noticeList = response.xpath("http://ul[@class="w_newslistpage_list"]//li")
#=======================================================
        #創(chuàng)建item實(shí)例
        item = JlshNoticeItem()
        for i, notice in enumerate(noticeList):
            item["noticeType"] = "公司通知"

            item["noticeTitle"] = notice.xpath(".//a/@title").extract()[0]

            item["noticeUrl"] = notice.xpath(".//a/@href").extract()[0]
#=======================================================
            dateItem = notice.xpath(".//span[2]/text()").extract()[0]
            pattern = re.compile(r"d+")
            datetime = pattern.findall(dateItem)
            yy = int(datetime[0])+2000
            mm = int(datetime[1])
            dd = int(datetime[2])
            item["noticeDate"] = date(yy,mm,dd)
#=======================================================
            content_html = requests.get(item["noticeUrl"]).text
            content_lxml = lxml.etree.HTML(content_html)
            content_table = content_lxml.xpath( 
                "http://div[@id="contentText"]/div[2]/div | 
                //div[@id="contentText"]/div[2]/p")
            
            
            item["noticeContent"] = []
            for j, p in enumerate(content_table):
                p = p.xpath("string(.)")
                #print("p:::::",p)
                p = p.replace("xa0"," ")
                p = p.replace("u3000", " ")
                item["noticeContent"].append(p)

            yield item
#=======================================================
        pages = response.xpath("http://div[@class="w_newslistpage_pager"]//span")
        nextPage = 0
        for i, page_tag in enumerate(pages):
            page = page_tag.xpath("./a/text()").extract()[0]
            page_url = page_tag.xpath("./a/@href").extract()
            if page == "下一頁(yè)>>":
                pattern = re.compile(r"d+")
                page_url = page_url[0]
                nextPage = int(pattern.search(page_url).group(0))
                break
#=======================================================
        if nextPage > 0 :
            postUrl = self.start_urls[0]
            formdata = {
                "MSOWebPartPage_PostbackSource":"",
                "MSOTlPn_SelectedWpId":"",
                "MSOTlPn_View":"0",
                "MSOTlPn_ShowSettings":"False",
                "MSOGallery_SelectedLibrary":"",
                "MSOGallery_FilterString":"",
                "MSOTlPn_Button":"none",
                "__EVENTTARGET":"",
                "__EVENTARGUMENT":"",
                "__REQUESTDIGEST":"",
                "MSOSPWebPartManager_DisplayModeName":"Browse",
                "MSOSPWebPartManager_ExitingDesignMode":"false",
                "MSOWebPartPage_Shared":"",
                "MSOLayout_LayoutChanges":"",
                "MSOLayout_InDesignMode":"",
                "_wpSelected":"",
                "_wzSelected":"",
                "MSOSPWebPartManager_OldDisplayModeName":"Browse",
                "MSOSPWebPartManager_StartWebPartEditingName":"false",
                "MSOSPWebPartManager_EndWebPartEditing":"false",
                "_maintainWorkspaceScrollPosition":"0",
                "__LASTFOCUS":"",
                "__VIEWSTATE":"",
                "__VIEWSTATEGENERATOR":"15781244",
                "query":"",
                "database":"GFHGXS-GFJLSH",
                "sUsername":"",
                "sAdmin":"",
                "sRoles":"",
                "activepage":str(nextPage),
                "__spDummyText1":"",
                "__spDummyText2":"",
                "_wpcmWpid":"",
                "wpcmVal":"",
            }

            yield FormRequest(postUrl,formdata=formdata, callback=self.parse)
說(shuō)明,以下說(shuō)明要配合上面源碼來(lái)看,不多帶帶標(biāo)注了
start_urls #要爬取的頁(yè)面地址,由于各個(gè)爬蟲(chóng)要爬取的頁(yè)面規(guī)則略有差異,所以做了6個(gè)爬蟲(chóng),而不是在一個(gè)爬蟲(chóng)中寫(xiě)入6個(gè)URL。通過(guò)查看scrapy源碼,我們能夠看到,start_urls中的地址會(huì)傳給一個(gè)內(nèi)件函數(shù)start_request(這個(gè)函數(shù)可以根據(jù)自己需要進(jìn)行重寫(xiě)),start_request向這個(gè)start_urls發(fā)送請(qǐng)求以后,所得到的response會(huì)直接轉(zhuǎn)到下面parse函數(shù)處理。
xpath ,下圖是頁(yè)面源碼:

通過(guò)xpath獲取到response中class類(lèi)是"w_newslistpage_list"的ul標(biāo)簽下的所有l(wèi)i標(biāo)簽,這里所得到的就是通知的列表,接下來(lái)我們?cè)谶@個(gè)列表中做循環(huán)。

先看下li標(biāo)簽內(nèi)的結(jié)構(gòu):

notice.xpath(".//a/@title").extract()[0] #獲取li標(biāo)簽內(nèi)a標(biāo)簽中的title屬性?xún)?nèi)容,這里就是通知標(biāo)題
notice.xpath(".//a/@href").extract()[0] #獲取li標(biāo)簽內(nèi)a標(biāo)簽中的href屬性?xún)?nèi)容,這里就是通知鏈接
notice.xpath(".//span[2]/text()").extract()[0] #獲取li標(biāo)簽內(nèi)第二個(gè)span標(biāo)簽中的內(nèi)容,這里是通知發(fā)布的日期
接下來(lái)幾行就是利用正則表達(dá)式講日期中的年、月、日三組數(shù)字提取出來(lái),在轉(zhuǎn)換為日期類(lèi)型存入item中。

再下一段,是獲得通知內(nèi)容,這里其實(shí)有兩種方案,一個(gè)是用scrapy的request發(fā)送給內(nèi)部爬蟲(chóng)引擎,得到另外一個(gè)response后再進(jìn)行處理,另一種就是我現(xiàn)在這樣直接去請(qǐng)求頁(yè)面。由于內(nèi)容頁(yè)面比較簡(jiǎn)單,只要獲得html代碼即可,所以就不麻煩scrapy處理了。
request.get得到請(qǐng)求頁(yè)面的html代碼
利用lxml庫(kù)的etree方法格式化html為xml結(jié)構(gòu)
利用xpath獲取到div[@id="contentText"]內(nèi)所有p標(biāo)簽、div標(biāo)簽節(jié)點(diǎn)。(可以得到99%以上的頁(yè)面內(nèi)容)
所得到的所有節(jié)點(diǎn)將是一個(gè)list類(lèi)型數(shù)據(jù),所有我們做一個(gè)for in循環(huán)
p.xpath("string(.)") 是獲取到p標(biāo)簽或div標(biāo)簽中的所有文本,而無(wú)視其他html標(biāo)簽。
用replace替換到頁(yè)面中的半角、全角空格(xa0、u3000)
每得到一行清洗過(guò)的數(shù)據(jù),就將其存入item["noticeContent"]中
最后將item輸出
在scrapy中,yield item后,item會(huì)提交給scrapy引擎,再又引擎發(fā)送給pipeline處理。pipeline一會(huì)再說(shuō)。
接下來(lái)的代碼就是處理翻頁(yè)。這里的頁(yè)面翻頁(yè)是利用js提交請(qǐng)求完成的,提交請(qǐng)求后,會(huì)response一個(gè)新的頁(yè)面列表

首先利用xpath找到頁(yè)面導(dǎo)航欄的節(jié)點(diǎn),在獲取到的所有節(jié)點(diǎn)中做for in循環(huán),直到找到帶有“下一頁(yè)”的節(jié)點(diǎn),這里有下一頁(yè)的頁(yè)碼,還是利用正則表達(dá)式來(lái)得到它,并將其轉(zhuǎn)為int類(lèi)型。

yield FormRequest(postUrl,formdata=formdata, callback=self.parse)
利用scrpay自帶的FormRequest發(fā)送post請(qǐng)求,這里的formdata是跟蹤post請(qǐng)求時(shí)得到的,要根據(jù)自己的網(wǎng)站調(diào)整,callback指示講得到的response反饋給parse函數(shù)處理(也就是新的一頁(yè)列表)
到此為止,就是spider文件的所有,這個(gè)文件唯一對(duì)外的輸出就是item,它會(huì)有scrapy引擎轉(zhuǎn)給pipeline處理
3. pipeline 代碼
from scrapy import signals
from scrapy.contrib.exporter import CsvItemExporter
from jlsh_notice import settings
import pymysql
import time

import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr


class JlshNoticePipeline(object):
    def process_item(self, item, spider):
        return item


# 用于數(shù)據(jù)庫(kù)存儲(chǔ)
class MySQLPipeline(object):
    def process_item(self, item, spider):
#=======================================================
        self.connect = pymysql.connect(
            host=settings.MYSQL_HOST,
            port=3306,
            db=settings.MYSQL_DBNAME,
            user=settings.MYSQL_USER,
            passwd=settings.MYSQL_PASSWD,
            charset="utf8",
            use_unicode=True)

        # 通過(guò)cursor執(zhí)行增刪查改
        self.cursor = self.connect.cursor()
#=======================================================
        # 查重處理
        self.cursor.execute(
            """select * from jlsh_weblist where 
                noticeType = %s and 
                noticeTitle = %s and
                noticeDate = %s """,
            (item["noticeType"], item["noticeTitle"], item["noticeDate"]))
        # 是否有重復(fù)數(shù)據(jù)
        repetition = self.cursor.fetchone()
#=======================================================
        # 重復(fù)
        if repetition:
            print("===== Pipelines.MySQLPipeline ===== 數(shù)據(jù)重復(fù),跳過(guò),繼續(xù)執(zhí)行..... =====")
        else:
            # 插入數(shù)據(jù)
            content_html = ""
            for p in item["noticeContent"]:
                content_html = content_html + "

" + p + "

" self.cursor.execute( """insert into jlsh_weblist(noticeType, noticeTitle, noticeDate, noticeUrl, noticeContent, record_time) value (%s, %s, %s, %s, %s, %s)""", (item["noticeType"], item["noticeTitle"], item["noticeDate"], item["noticeUrl"], content_html, time.localtime(time.time()))) try: # 提交sql語(yǔ)句 self.connect.commit() print("===== Insert Success ! =====", item["noticeType"], item["noticeTitle"], item["noticeDate"], item["noticeUrl"]) except Exception as error: # 出現(xiàn)錯(cuò)誤時(shí)打印錯(cuò)誤日志 print("===== Insert error: %s ====="%error) #======================================================= #定向發(fā)送郵件 if settings.SEND_MAIL: sender="***@***.com" # 發(fā)件人郵箱賬號(hào) password = "********" # 發(fā)件人郵箱密碼 receiver="*****@*****.com" # 收件人郵箱賬號(hào),我這邊發(fā)送給自己 title = item["noticeTitle"] content = """

%s

%s

%s

%s """ % (item["noticeType"], item["noticeUrl"], item["noticeTitle"], item["noticeDate"], content_html) ret=self.sendMail(sender, password, receiver, title, content) if ret: print("郵件發(fā)送成功") else: print("郵件發(fā)送失敗") pass self.connect.close() return item #======================================================= def sendMail(self, sender, password, receiver, title, content): ret=True try: msg=MIMEText(content,"html","utf-8") msg["From"]=formataddr(["", sender]) # 括號(hào)里的對(duì)應(yīng)發(fā)件人郵箱昵稱(chēng)、發(fā)件人郵箱賬號(hào) msg["To"]=formataddr(["",receiver]) # 括號(hào)里的對(duì)應(yīng)收件人郵箱昵稱(chēng)、收件人郵箱賬號(hào) msg["Subject"]="郵件的主題 " + title # 郵件的主題,也可以說(shuō)是標(biāo)題 server=smtplib.SMTP("smtp.*****.***", 25) # 發(fā)件人郵箱中的SMTP服務(wù)器,端口是25 server.login(sender, password) # 括號(hào)中對(duì)應(yīng)的是發(fā)件人郵箱賬號(hào)、郵箱密碼 server.sendmail(sender,[receiver,],msg.as_string()) # 括號(hào)中對(duì)應(yīng)的是發(fā)件人郵箱賬號(hào)、收件人郵箱賬號(hào)、發(fā)送郵件 server.quit() # 關(guān)閉連接 except Exception: # 如果 try 中的語(yǔ)句沒(méi)有執(zhí)行,則會(huì)執(zhí)行下面的 ret=False ret=False return ret #=======================================================
說(shuō)明
這里的pipeline是我自己建立的,寫(xiě)好后在setting中改一下設(shè)置就可以了。因?yàn)閟crapy的去重機(jī)制只針對(duì)爬蟲(chóng)一次運(yùn)行過(guò)程有效,多次循環(huán)爬取就不行了,所以為了實(shí)現(xiàn)不爬取重復(fù)數(shù)據(jù),使用mysql就是比較靠譜的選擇了。
pymysql是python鏈接mysql的包,沒(méi)有的話(huà)pip安裝即可。
首先建立一個(gè)pymysql.connect實(shí)例,將連接mysql的幾個(gè)參數(shù)寫(xiě)進(jìn)去,我這里是先寫(xiě)到setting里面再導(dǎo)入,也可以直接寫(xiě),值得注意的是port參數(shù)(默認(rèn)是3306)不要加引號(hào),因?yàn)樗仨毷莍nt類(lèi)型的。
接下來(lái)建立一個(gè)cursor實(shí)例,用于對(duì)數(shù)據(jù)表進(jìn)行增刪查改。
cursor.execute() 方法是定義要執(zhí)行的sql命令,這里注意就是execute只是定義,不是執(zhí)行。
cursor.fetchone() 方法是執(zhí)行sql并返回成功與否的結(jié)果。這里進(jìn)行了數(shù)據(jù)查詢(xún),如果能夠查到,說(shuō)明這條記錄已經(jīng)建立,如果沒(méi)有,就可以新增數(shù)據(jù)了。
由mysql數(shù)據(jù)庫(kù)不接受list類(lèi)型的數(shù)據(jù),所以接下來(lái)要對(duì)item["noticeContent"]做一下處理(他是list類(lèi)型的,還記得么^_^)。在item["noticeContent"]中做for in循環(huán),把他的每一項(xiàng)內(nèi)容用

標(biāo)簽包起來(lái),組成一個(gè)長(zhǎng)字符串。

接下來(lái)還是寫(xiě)sql命令:insert into .....
寫(xiě)完以后用connect.commit()提交執(zhí)行
最后就是發(fā)送郵件了,自建一個(gè)sendMail函數(shù),發(fā)送郵件用到了兩個(gè)python包:smtplib 和 email,具體沒(méi)啥說(shuō)的,照著寫(xiě)就行了,我是一次成功。。
到此為止,就可以運(yùn)行爬蟲(chóng)了,可以看到數(shù)據(jù)庫(kù)中已經(jīng)有了爬取的內(nèi)容。。。

4. settings.py
注冊(cè)pipeline
ITEM_PIPELINES = {
    "jlsh_notice.pipelines.MySQLPipeline": 300,
}
log輸出的定義,四個(gè)任選其一
LOG_LEVEL = "INFO"
LOG_LEVEL = "DEBUG"
LOG_LEVEL = "WARNING"
LOG_LEVEL = "CRITICAL"
關(guān)于爬蟲(chóng)終止條件的定義,默認(rèn)不設(shè)置
#在指定時(shí)間過(guò)后,就終止爬蟲(chóng)程序.
CLOSESPIDER_TIMEOUT = 60

#抓取了指定數(shù)目的Item之后,就終止爬蟲(chóng)程序.
CLOSESPIDER_ITEMCOUNT = 10

#在收到了指定數(shù)目的響應(yīng)之后,就終止爬蟲(chóng)程序.
CLOSESPIDER_PAGECOUNT = 100

#在發(fā)生了指定數(shù)目的錯(cuò)誤之后,就終止爬蟲(chóng)程序.
CLOSESPIDER_ERRORCOUNT = 100
5. 實(shí)現(xiàn)自動(dòng)執(zhí)行 (1) 同時(shí)執(zhí)行多個(gè)爬蟲(chóng)。

首先,在項(xiàng)目目錄下建立新的目錄(與spider目錄同級(jí)),名為“commands”,內(nèi)建兩個(gè)文件:

__init__.py    (空文件,但是要有)
crawlall.py
from scrapy.commands import ScrapyCommand
from scrapy.utils.project import get_project_settings
 
 
class Command(ScrapyCommand):
 
    requires_project = True
 
    def syntax(self):
        return "[options]"
 
    def short_desc(self):
        return "Runs all of the spiders"
 
    def run(self, args, opts):
        spider_list = self.crawler_process.spiders.list()
        for name in spider_list:
            self.crawler_process.crawl(name, **opts.__dict__)
        self.crawler_process.start()
然后在項(xiàng)目目錄下建立一個(gè)setup.py文件
from setuptools import setup, find_packages

setup(name="scrapy-mymodule",
    entry_points={
        "scrapy.commands": [
            "crawlall=jlsh_notice.commands:crawlall",
            ],
        },
    )
這個(gè)時(shí)候,在scrapy項(xiàng)目目錄下執(zhí)行scrapy crawlall即可運(yùn)行所有的爬蟲(chóng)
(2) 每隔一段時(shí)間運(yùn)行爬蟲(chóng)。

在項(xiàng)目目錄下新建一個(gè)noticeStart.py文件(名稱(chēng)任意),利用python中的os和time包實(shí)現(xiàn)每隔一段時(shí)間運(yùn)行一個(gè)命令。

import time
import os

while True:
    os.system("scrapy crawlall")
    remindTime = 5
    remindCount = 0
    sleepTime = 60
    while remindCount * remindTime < sleepTime:
        time.sleep(remindTime*60)
        remindCount = remindCount + 1
        print("已等待%s分鐘,距離下一次搜集數(shù)據(jù)還有%s分鐘......"%(remindCount*remindTime,(sleepTime/remindTime-(remindCount))*remindTime))   
    
(3) 實(shí)現(xiàn)開(kāi)機(jī)運(yùn)行。

首先:由于cmd命令打開(kāi)目錄在c盤(pán),我的scrapy項(xiàng)目在e盤(pán),所以要做一個(gè)bat文件跳轉(zhuǎn)目錄并運(yùn)行py文件

autorun.bat
e:
cd e:PythonProjectsScrapyProjectsjlsh_noticejlsh_notice
python noticeStart.py

其次:打開(kāi)計(jì)劃任務(wù)程序,創(chuàng)建基本任務(wù),運(yùn)行程序選擇剛剛的bat文件,值得說(shuō)明的是,計(jì)劃任務(wù)觸發(fā)器不要設(shè)置啟動(dòng)后立即執(zhí)行,不然可能會(huì)失敗,要延遲1分鐘運(yùn)行。

到此為止,所有的代碼完成,以后還要根據(jù)實(shí)際情況增加更多的通知類(lèi)別,也可以根據(jù)不同領(lǐng)導(dǎo)的關(guān)注點(diǎn)不同,分別發(fā)送郵件提醒。歡迎有興趣的朋友留言交流。。。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/42115.html

相關(guān)文章

  • 如何通過(guò) Scrapyd + ScrapydWeb 簡(jiǎn)單高效地部署和監(jiān)控分布式爬蟲(chóng)項(xiàng)目

    摘要:支持一鍵部署項(xiàng)目到集群。添加郵箱帳號(hào)設(shè)置郵件工作時(shí)間和基本觸發(fā)器,以下示例代表每隔小時(shí)或當(dāng)某一任務(wù)完成時(shí),并且當(dāng)前時(shí)間是工作日的點(diǎn),點(diǎn)和點(diǎn),將會(huì)發(fā)送通知郵件。除了基本觸發(fā)器,還提供了多種觸發(fā)器用于處理不同類(lèi)型的,包括和等。 showImg(https://segmentfault.com/img/remote/1460000018772067?w=1680&h=869); 安裝和配置 ...

    zsirfs 評(píng)論0 收藏0
  • 部署Scrapy分布式爬蟲(chóng)項(xiàng)目

    摘要:以上示例代表當(dāng)發(fā)現(xiàn)條或條以上的級(jí)別的時(shí),自動(dòng)停止當(dāng)前任務(wù),如果當(dāng)前時(shí)間在郵件工作時(shí)間內(nèi),則同時(shí)發(fā)送通知郵件。 showImg(https://segmentfault.com/img/remote/1460000018052810); 一、需求分析 初級(jí)用戶(hù): 只有一臺(tái)開(kāi)發(fā)主機(jī) 能夠通過(guò) Scrapyd-client 打包和部署 Scrapy 爬蟲(chóng)項(xiàng)目,以及通過(guò) Scrapyd JS...

    techstay 評(píng)論0 收藏0
  • 常見(jiàn)的企業(yè)管理系統(tǒng)

    摘要:功能介紹軟件的核心應(yīng)用是流程審批協(xié)同工作公文管理國(guó)企和政府機(jī)關(guān)溝通工具文檔管理信息中心電子論壇計(jì)劃管理項(xiàng)目管理任務(wù)管理會(huì)議管理關(guān)聯(lián)人員系統(tǒng)集成門(mén)戶(hù)定制通訊錄工作便簽問(wèn)卷調(diào)查常用工具計(jì)算器萬(wàn)年歷等。 清單 ERP進(jìn)銷(xiāo)存管理系統(tǒng) OA協(xié)同辦公管理系統(tǒng) CRM客戶(hù)關(guān)系管理系統(tǒng) HRM人力資源管理系統(tǒng) EAM資產(chǎn)管理系統(tǒng) 績(jī)效管理系統(tǒng) 成本管理系統(tǒng) 設(shè)備管理系統(tǒng) 質(zhì)量管理系統(tǒng) ERP進(jìn)銷(xiāo)存...

    bladefury 評(píng)論0 收藏0
  • 告警分析:如何幫助運(yùn)維團(tuán)隊(duì)快速做出最佳決策?

    摘要:健全的告警分析體系真正認(rèn)識(shí)你的團(tuán)隊(duì)好的告警分析機(jī)制能夠幫助管理者分析團(tuán)隊(duì)整體的工作情況,根據(jù)作為評(píng)判標(biāo)準(zhǔn)。根據(jù)告警內(nèi)容分析也是很有必要的,能夠幫助團(tuán)隊(duì)管理者對(duì)資源進(jìn)行適當(dāng)?shù)恼{(diào)整,工作重心的調(diào)整。 「路漫漫其修遠(yuǎn)兮,吾將上下而求索」,「轉(zhuǎn)身」不見(jiàn)得華麗,但我必須「轉(zhuǎn)身」,不要安逸于現(xiàn)在的運(yùn)維狀況。 如果你運(yùn)維一線人員,是否會(huì)遇到以下情況: 公司所有的服務(wù)器告警消息會(huì)塞滿(mǎn)自己的整個(gè)郵箱,...

    pumpkin9 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<