上市公司重要公告集錦抓取

在金融機(jī)構(gòu)工作,每天早晨的晨會不可避免,晨會主要的環(huán)節(jié)是了解當(dāng)天的上市公司公告沙庐。本文提供一個簡易實現(xiàn),自動抓取公告集錦佳吞,并郵件及時推送拱雏。

爬蟲主要功能結(jié)構(gòu)

notice_montage 可以做到拆箱即用。主要包括如下功能:

  • 代碼實現(xiàn)
    • 初始化配置文件及日志
    • 使用requests抓取網(wǎng)頁頁面
    • 解析入口頁底扳,解析公告頁內(nèi)容
    • 分析公告頁內(nèi)容并進(jìn)行一些業(yè)務(wù)處理
    • 郵件通知推送
  • 代碼部署
    • windows機(jī)器使用定時計劃自動執(zhí)行
    • 阿里云服務(wù)自動執(zhí)行

代碼實現(xiàn)

1.1 初始化配置及日志

項目含有郵件地址等敏感信息铸抑,將其獨(dú)立出來形成配置文件,更利于項目部署花盐。對配置文件利用ConfigParser模塊進(jìn)行解析羡滑,代碼如下:

<pre>
def get_config_parser():
config_file_path = "notice_montage.ini"
cf = ConfigParser.ConfigParser()
cf.read(config_file_path)
return cf

解析配置

def init_config():
cf = get_config_parser()
global DEBUG, INTERVAL, WEBSITE
INTERVAL = int(cf.get("timeconf", "interval"))
DEBUG = cf.get("urlconf", "debug") == 'True'
WEBSITE = cf.get("urlconf", "website")
</pre>

配置文件notice_montage.ini,內(nèi)容如下:

<pre>
[urlconf]
website = http://www.ccstock.cn/meiribidu/jiaoyitishi/
debug = True

[timeconf]
interval = 10

[mailconf]

接收通知的郵箱,多個郵箱使用,分割

to_list = xxx@foxmail.com ,xxx@qq.com

設(shè)置服務(wù)器

mail_host = smtp.exmail.qq.com

替換為發(fā)件郵箱用戶名

mail_username = xxx

發(fā)件郵箱用戶名

mail_user = xxx

發(fā)件郵箱口令密碼

mail_pass = xxx

發(fā)件箱的后綴

mail_postfix = xxx
</pre>

爬蟲部署后算芯,自動運(yùn)行柒昏,適當(dāng)?shù)挠涗浺恍┪募罩荆欣谧粉櫯老x的運(yùn)作運(yùn)行狀況熙揍,做到有跡可查职祷。日志記錄利用logging模塊。

<pre>

日志記錄器

logger = logging.getLogger()
def init_log():
if DEBUG:
handler = logging.StreamHandler()
else:
handler = logging.FileHandler("notice_montage.log")
formatter = logging.Formatter(
'%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
</pre>

測試情況下届囚,日志輸出到控制臺有梆,會更方便調(diào)試;正式部署后意系,輸出到文件泥耀,要進(jìn)行切換,直接修改notice_montage.ini中的debug值蛔添。

1.2 使用requests抓取網(wǎng)頁頁面

<pre>
def download_get_html(url, charset="utf-8", timeout=10, num_retries=3):
UA = random.choice(user_agent_list)
headers = {
'User-Agent': UA,
'Content-Type': 'text/html; charset=' + charset
}
try:
response = requests.get(url, headers=headers,
timeout=timeout)
response.encoding = charset
if response.status_code == 404:
logger.debug('get 404: %s ', url)
return None
else:
logger.debug('get : %s ', url)
return response.text
except:
if num_retries > 0:
time.sleep(10)
logger.debug('正在嘗試痰催,10S后將重新獲取倒數(shù)第 %d 次', num_retries)
return download_get_html(url, charset, timeout, num_retries - 1)
else:
logger.debug('嘗試也不好使了!取消訪問')
return None
</pre>

download_get_html 是一個和業(yè)務(wù)無關(guān)的工具函數(shù)迎瞧,主要使用request的get方法下載指定URL的內(nèi)容夸溶。為了讓下載更友好,模擬了User-Agent凶硅,并自動嘗試3次缝裁。

1.3 使用BeautifulSoup解析頁面內(nèi)容

使用download_get_html獲取頁面內(nèi)容后,使用BeautifulSoup對其進(jìn)行解析足绅,獲取需要的信息捷绑。

解析入口列表頁內(nèi)容

入口頁韩脑,是所有交易公告的列表清單,使用chrome的開發(fā)者工具胎食,查看頁面代碼如下圖:

Paste_Image.png

列表按照時間進(jìn)行倒序排列扰才,晨報只需要最新的一條公告集錦頁面,所以只需要找到class為listMain的div的第一個li類型子元素厕怜,代碼如下:

<pre>

獲取當(dāng)期集錦的url

def parser_list_page(html_doc, now):
soup = BeautifulSoup(html_doc, 'lxml', from_encoding='utf-8')
# 只找第一個標(biāo)簽
tag = soup.find("div", class_="listMain").find("li")
link_tag = tag.find("a")
span_tag = tag.find("span")
page_url = link_tag['href']
# 截取日期
date_string = span_tag.string[0:10]
if date_string == now:
return page_url
else:
return None
</pre>

now參數(shù)為當(dāng)期的時間衩匣,用于核對當(dāng)期公告是否更新。已更新則返回次日集錦鏈接粥航,未更新則返回空琅捏。

解析內(nèi)容頁內(nèi)容

獲取公告集錦頁地址后,繼續(xù)使用download_get_html獲取內(nèi)容頁內(nèi)容,如下圖:

Paste_Image.png

只需要找到id為newscontent的div即可递雀,代碼如下:

<pre>
def parser_item_page(html_doc, now):
soup = BeautifulSoup(html_doc, 'lxml', from_encoding='utf-8')
# title = soup.find("h1").string
newscontent = soup.find("div", id="newscontent")
html = newscontent.prettify()
return html
</pre>

1.4 分析頁面內(nèi)容

公告中數(shù)字都采用統(tǒng)計技術(shù)柄延,并不利用閱讀,我們利用正則將其進(jìn)行處理缀程。
例如:
<pre>
杰克股份(603337)7月23日晚間公告搜吧,截至2017年7月21日,公司2017年員工持股計劃通過二級市場買入方式增持公司股票3杨凑,468滤奈,534股,占公司已發(fā)行股本1.68%撩满。成交合計金額133蜒程,786,450.45元伺帘,成交均價38.57元昭躺。
</pre>

將其中的股數(shù)和成交金額進(jìn)行轉(zhuǎn)換,轉(zhuǎn)換后如下:

<pre>
杰克股份(603337)7月23日晚間公告伪嫁,截至2017年7月21日领炫,公司2017年員工持股計劃通過二級市場買入方式增持公司股票3,468张咳,534股(346.8534萬股)驹吮,占公司已發(fā)行股本1.68%。成交合計金額133晶伦,786,450.45元(1.3378645045億元)啄枕,成交均價38.57元婚陪。
</pre>

這樣閱讀起來更符合習(xí)慣。格式化股份數(shù)代碼如下:

<pre>

格式化股份計數(shù)

def transform_gu(lineText):
p = re.compile(u"[\d频祝,]\d+股")
searchObj = re.findall(p, lineText)
if searchObj:
for x in xrange(0, len(searchObj)):
s1 = searchObj[x]
ns = filter(lambda ch: ch in '0123456789', s1)
nb = float(ns)
if nb >= 100000000:
s2 = str(nb / 100000000) + "億股"
lineText = lineText.replace(s1, s1 + "(" + s2 + ")")
elif nb >= 10000:
s2 = str(nb / 10000) + "萬股"
lineText = lineText.replace(s1, s1 + "(" + s2 + ")")
return lineText
</pre>

核心正則代碼<code>u"[\d泌参,]\d+股"</code>,表示至少含有任意個數(shù)字+,脆淹,然后連接至少一個數(shù)字,以“股”字結(jié)尾沽一,匹配上3盖溺,468,534股這樣的字符
串铣缠。

還可以對公告集錦匹配自選股池烘嘱,做重點(diǎn)提醒;對大股東增持的利好消息蝗蛙,進(jìn)行特殊提示蝇庭。篇幅有限,涉及具體業(yè)務(wù)捡硅,處理方法也比較一致哮内,本文就不進(jìn)行展示。

1.5 郵件通知推送

公告獲取后壮韭,立即推送給目標(biāo)用戶北发,做到快人一步。

<pre>
def send_notice_mail(html, now):
cf = get_config_parser()
to_list = cf.get("mailconf", "to_list").split(",")
mail_host = cf.get("mailconf", "mail_host")
mail_username = cf.get("mailconf", "mail_username")
mail_user = cf.get("mailconf", "mail_user")
mail_pass = cf.get("mailconf", "mail_pass")
mail_postfix = cf.get("mailconf", "mail_postfix")
me = "AStockMarketNoticeWatcher" + "<" +
mail_username + "@" + mail_postfix + ">"
msg = MIMEMultipart()
subject = now + ' 日 - 二級市場重要公告集錦'
msg['Subject'] = Header(subject, 'utf-8')
msg['From'] = me
msg['To'] = ";".join(to_list)
mail_msg = html
# 郵件正文內(nèi)容
msg.attach(MIMEText(mail_msg, 'html', 'utf-8'))

try:
    server = smtplib.SMTP()
    server.connect(mail_host)
    server.ehlo()
    server.starttls()
    server.login(mail_user, mail_pass)
    server.sendmail(me, to_list, msg.as_string())
    server.close()
    logger.debug('sent mail successfully')
except smtplib.SMTPException, e:
    logger.debug('Error: 無法發(fā)送郵件 %s ', repr(e))

</pre>

代碼部署

2.1 windows 系統(tǒng)下定時任務(wù)自動執(zhí)行

windows的定時任務(wù)喷屋,需要先編寫bat腳本琳拨,代碼非常簡單,類似<code>python notice_montage.py</code>逼蒙,autorun.bat 代碼如下:

<pre>
:: 自動運(yùn)行腳本
:: 需更換為本機(jī)路徑
c:\python27\python.exe D:\xampp\htdocs\ding\morning\notice_montage.py %*
</pre>

在自動執(zhí)行前从绘,記得切換notice_montage.ini的debug值為False,留下日志文件是牢,方便跟蹤結(jié)果僵井。

打開【計劃任務(wù)程序】,選擇右側(cè)【操作】中的【創(chuàng)建任務(wù)】

Paste_Image.png

需要注意的是驳棱,勾選【不管用戶是否登錄都要運(yùn)行】批什,這樣系統(tǒng)待機(jī)狀態(tài)下也可以執(zhí)行∩缃粒【觸發(fā)器】頁簽中驻债,新建觸發(fā)器:

Paste_Image.png

根據(jù)需要,設(shè)置成每天定點(diǎn)到10點(diǎn)即可形葬。(實際代碼中合呐,進(jìn)行了自動嘗試,如果公告10點(diǎn)沒更新笙以,會10分鐘后嘗試一次淌实,自動嘗試3次)

【操作】頁簽中,新建操作:

Paste_Image.png

程序和腳本,選擇前面創(chuàng)建的autorun.bat

確定后拆祈,就可以自動運(yùn)行了恨闪,每天收到公告。

2.2 阿里云服務(wù)器自動執(zhí)行

服務(wù)器部署好python/virtualenv后放坏,編寫crontab命令

<pre>
[root@iZ253amoxhcZ morning]# crontab -l
00 22 * * 0-5 /uy/flask-venv/bin/python notice_montage.py
</pre>

其中<code>/uy/flask-venv/bin/python</code>是virtualenv的路徑咙咽,<code>00 22 * * 0-5</code> 表示周日-周五每天22點(diǎn)調(diào)度。

最后淤年,爬蟲源代碼在(叮)[https://github.com/thebe2/ding] 钧敞,喜歡的請給個星。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末互亮,一起剝皮案震驚了整個濱河市犁享,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌豹休,老刑警劉巖炊昆,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異威根,居然都是意外死亡凤巨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門洛搀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來敢茁,“玉大人,你說我怎么就攤上這事留美♂C” “怎么了菲语?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵屯吊,是天一觀的道長韵洋。 經(jīng)常有香客問我,道長景图,這世上最難降的妖魔是什么较雕? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮挚币,結(jié)果婚禮上亮蒋,老公的妹妹穿的比我還像新娘。我一直安慰自己妆毕,他們只是感情好慎玖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著笛粘,像睡著了一般凄吏。 火紅的嫁衣襯著肌膚如雪远舅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天痕钢,我揣著相機(jī)與錄音,去河邊找鬼序六。 笑死任连,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的例诀。 我是一名探鬼主播随抠,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼繁涂!你這毒婦竟也來了拱她?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤扔罪,失蹤者是張志新(化名)和其女友劉穎秉沼,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體矿酵,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡唬复,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了全肮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片敞咧。...
    茶點(diǎn)故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖辜腺,靈堂內(nèi)的尸體忽然破棺而出休建,到底是詐尸還是另有隱情,我是刑警寧澤评疗,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布测砂,位于F島的核電站,受9級特大地震影響壤巷,放射性物質(zhì)發(fā)生泄漏邑彪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一胧华、第九天 我趴在偏房一處隱蔽的房頂上張望寄症。 院中可真熱鬧,春花似錦矩动、人聲如沸有巧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽篮迎。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間甜橱,已是汗流浹背逊笆。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留岂傲,地道東北人难裆。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像镊掖,于是被迫代替她去往敵國和親乃戈。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,185評論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理亩进,服務(wù)發(fā)現(xiàn)症虑,斷路器,智...
    卡卡羅2017閱讀 134,672評論 18 139
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫归薛、插件谍憔、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,107評論 4 62
  • 利用網(wǎng)上現(xiàn)成的的接口,用python練習(xí)了下(又碰到了中文編碼問題了:獲取的頁面源碼 編碼就是整不成中文) 天氣查...
    倔強(qiáng)的瀟灑小姐閱讀 1,284評論 6 4
  • 色彩是一種奇怪的東西沈条,它是美麗而豐富的,它能喚起人類的心靈感知诅炉。一般來說蜡歹,紅色是火的顏色,熱情涕烧、奔放月而;也是血的顏色...
    曹陽CY閱讀 371評論 0 0