上市公司公告大全抓取

東方財(cái)富網(wǎng)提供了上市公司的公告大全思币,將其抓取出來逃片,進(jìn)行整理后空郊,提供給基金經(jīng)理做投資決策。本文介紹了該項(xiàng)目的python爬蟲實(shí)現(xiàn)過程丈攒。

  • 需求分析
    • 業(yè)務(wù)分析
    • 頁面數(shù)據(jù)分析
    • 程序結(jié)構(gòu)設(shè)計(jì)
  • 編碼實(shí)現(xiàn)
    • 基礎(chǔ)工具函數(shù)
    • 邏輯實(shí)現(xiàn)

需求分析

1.1 業(yè)務(wù)分析

分析公告匯總頁面哩罪,發(fā)現(xiàn)滬深A(yù)股公告中小板公告巡验、創(chuàng)業(yè)板公告际插,頁面表現(xiàn)比較一致,而三板公告實(shí)現(xiàn)方式有所變化显设,先抓取滬深A(yù)股公告框弛、中小板公告和創(chuàng)業(yè)板公告

1.2 頁面數(shù)據(jù)分析

翻頁頁面,發(fā)現(xiàn)地址欄鏈接不變捕捂,數(shù)據(jù)是采用ajax動(dòng)態(tài)加載瑟枫。

Paste_Image.png

在chrome的Network中找到數(shù)據(jù)請(qǐng)求地址:
<pre>
http://data.eastmoney.com/notices/getdata.ashx?StockCode=&FirstNodeType=0&CodeType=1&PageIndex=2&PageSize=50&jsObj=LYqzjWvf&SecNodeType=0&Time=&rt=50032558
http://data.eastmoney.com/notices/getdata.ashx?StockCode=&FirstNodeType=0&CodeType=1&PageIndex=3&PageSize=50&jsObj=maFEjDLX&SecNodeType=0&Time=&rt=50032562
</pre>

同時(shí)在網(wǎng)頁源代碼中也發(fā)現(xiàn):
<pre>
dataurl: "/notices/getdata.ashx?StockCode=&FirstNodeType=0&CodeType=3&PageIndex={page}&PageSize={pageSize}&jsObj={jsname}{param}",

</pre>

對(duì)比大概可以肯定如下參數(shù):
<pre>
CodeType 公告板塊分類
PageIndex 頁面序號(hào)
PageSize 頁面大小
</pre>
不太確定的是<code>jsObj</code>和<code>rt</code>這2個(gè)參數(shù)斗搞。

繼續(xù)分析網(wǎng)絡(luò)請(qǐng)求,發(fā)現(xiàn)有一個(gè)load_table_data.js的請(qǐng)求慷妙,看起來比較可疑榜旦。在load_table_data.js中搜索jsObj未發(fā)現(xiàn),但是搜索&rt發(fā)現(xiàn)下面代碼:
<pre>
update: function () {
var _t = this;
if (_t.options.beforeupdate(_t))
return;
var jsname = _t.getCode(8),
_url = _t.parperUrl();
_t.options.code = jsname;
_url = _url.replace("{jsname}", jsname);
_url += (_url.indexOf('?') > -1) ? "&rt=" : "?rt=";
_url += parseInt(parseInt(new Date().getTime()) / 30000);
_t.loadThead();
_t.scorllTop();
_t.showLoading();
_t.tools.loadJs(_url, _t.options.charset,
function () {
if (typeof (_t.options.load_div) != "undefined") {
if (_t.options && _t.options.nodetemp) {
_t.options.nodetemp.style.position = "";
}
_t.options.load_div.style.display = "none"
}
if (!(eval("typeof " + jsname) == "undefined") || eval("typeof " + jsname == null)) {
var loaddata = eval(jsname);
if (jsname != _t.options.code) {
return
}
_t.options.data = loaddata;
_t.display()
} else {
// alert("數(shù)據(jù)加載失敗景殷,請(qǐng)刷新頁面重新嘗試!")
if (console && console.log) {
console.log("tools.loadJs掛了稍后再改");
}
}
})
},
</pre>
大概就是這里了澡屡,在257行猿挚,加上斷點(diǎn)調(diào)試一下(如果對(duì)前端不太熟悉,調(diào)試方式是在chrome開發(fā)者工具的【Sources】標(biāo)簽里驶鹉,找到load_table_data.js 绩蜻,鼠標(biāo)點(diǎn)擊257行)

Paste_Image.png

這樣就確認(rèn)了鏈接里的<code>jsObj</code>和<code>rt</code>的實(shí)現(xiàn)方法。
jsObj生成函數(shù)如下:
<pre>
getCode: function (num) {
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var codes = str.split('');
num = num || 6;
var code = "";
for (var i = 0; i < num; i++) {
code += codes[Math.floor(Math.random() * 52)]
}
return code
},
var jsname = _t.getCode(8),
</pre>

rt生成代碼如下
<pre>
parseInt(parseInt(new Date().getTime()) / 30000)
</pre>

1.3 程序結(jié)構(gòu)設(shè)計(jì)
Paste_Image.png

(直接使用有道云筆記md畫的圖室埋,有點(diǎn)渣)

編碼實(shí)現(xiàn)

基礎(chǔ)工具函數(shù)
# load_table_data.js getCode
def getCode(num=6):
    s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    codes = list(s)
    code = ""
    for x in xrange(0, num):
        idx = int(math.floor(random() * 52))
        code += codes[idx]
    return code
  • rt 模擬函數(shù)
# _url += parseInt(parseInt(new Date().getTime()) / 30000);
def getRightTime():
    r = int(time.time() / 30)
    return r
    mail_msg = read_html(now)
    # 郵件正文內(nèi)容
    # msg.attach(MIMEText(now+" 日,二級(jí)市場(chǎng)公告信息姚淆。詳情請(qǐng)見附件excel", 'plain', 'utf-8'))
    msg.attach(MIMEText(mail_msg, 'html', 'utf-8'))

    # 構(gòu)造附件2孕蝉,傳送當(dāng)前目錄下的 xls 文件
    att2 = MIMEText(open(fileName, 'rb').read(), 'base64', 'utf-8')
    att2["Content-Type"] = 'application/octet-stream'
    # 解決中文附件下載時(shí)文件名亂碼問題
    att2.add_header('Content-Disposition', 'attachment', filename='=?utf-8?b?' +
                    base64.b64encode(fileName.encode('UTF-8')) + '?=')
    msg.attach(att2)
  • 日期比較
def time_compare(notice_date):
    tt = time.mktime(time.strptime(notice_date, "%Y-%m-%d"))
    # 得到公告的時(shí)間戳
    if noticeCate == 1:
        # A股公告取當(dāng)日
        # 得到本地時(shí)間(當(dāng)日零時(shí))的時(shí)間戳
        st = time.strftime("%Y-%m-%d", time.localtime(time.time()))
    else:
        # 新三板公告取前日
        # 得到本地時(shí)間(當(dāng)日零時(shí))的時(shí)間戳
        st = time.strftime(
            "%Y-%m-%d", time.localtime(time.time() - 60 * 60 * 24))
    t = time.strptime(st, "%Y-%m-%d")
    now_ticks = time.mktime(t)
    # 周一需要是大于
    if tt >= now_ticks:
        return True
    else:
        return False
  • excel讀寫
# 寫excel
def write_sheet(workbook, sheetName, rows):
    worksheet = workbook.add_sheet(sheetName)
    worksheet.write(0, 0, label="代碼")
    worksheet.write(0, 1, label="名稱")
    worksheet.write(0, 2, label="公告標(biāo)題")
    worksheet.write(0, 3, label="公告類型")
    for x in xrange(0, len(rows)):
        row = rows[x]
        for y in xrange(0, 4):
            if y == 2:
                alink = 'HYPERLINK("%s";"%s")' % (row[4], row[2])
                worksheet.write(x + 1, y, xlwt.Formula(alink))
            else:
                item = row[y]
                worksheet.write(x + 1, y, item)
# 打開excel
def open_excel(file='file.xls'):
    try:
        data = xlrd.open_workbook(file)
        return data
    except Exception, e:
        logger.debug(str(e))
  • 數(shù)據(jù)循環(huán)下載
def do_notice(notices, plate):
    for page in xrange(1, 10):
        rt = getRightTime()
        code = getCode(8)
        url = getUrl(apiurl, plate["codeType"], page, code, rt)
        jsdata = download_get_html(url)
        if jsdata != None:
            json_str = jsdata[15:-1]
            datas = json.loads(json_str)["data"]
            for data in datas:
                # 公告日期
                notice = parser_data(data)
                if notice != None:
                    notices.append(notice)
                else:
                    logger.debug("page end notices %s %d"& (plate["name"], len(notices)))
                    return
        else:
            logger.debug("no  notices %s %d"& (plate["name"], len(notices)))
            return
  • 數(shù)據(jù)解析
def parser_data(data):
    temp = data["CDSY_SECUCODES"][0]
    noteicedate = data["NOTICEDATE"]
    date = noteicedate[0:noteicedate.index('T')]
    code = temp["SECURITYCODE"]
    name = temp["SECURITYSHORTNAME"]
    title = data["NOTICETITLE"]
    typeName = '公司公告'
    if data["ANN_RELCOLUMNS"] and len(data["ANN_RELCOLUMNS"]) > 0:
        typeName = data["ANN_RELCOLUMNS"][0]["COLUMNNAME"]
    namestr = unicode(name).encode("utf-8")
    detailLink = baseurl + '/notices/detail/' + code + '/' + \
        data["INFOCODE"] + ',' + \
        base64.b64encode(urllib.quote(namestr)) + '.html'
    # print date,code,name,title,typeName,detailLink
    if time_compare(date):
        return [code, name, title, typeName, detailLink, date]
    else:
        return None
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市腌逢,隨后出現(xiàn)的幾起案子降淮,更是在濱河造成了極大的恐慌,老刑警劉巖搏讶,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佳鳖,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡媒惕,警方通過查閱死者的電腦和手機(jī)系吩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妒蔚,“玉大人穿挨,你說我怎么就攤上這事∶婢Γ” “怎么了絮蒿?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)叁鉴。 經(jīng)常有香客問我土涝,道長(zhǎng),這世上最難降的妖魔是什么幌墓? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任但壮,我火速辦了婚禮冀泻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蜡饵。我一直安慰自己弹渔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布溯祸。 她就那樣靜靜地躺著肢专,像睡著了一般。 火紅的嫁衣襯著肌膚如雪焦辅。 梳的紋絲不亂的頭發(fā)上博杖,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音筷登,去河邊找鬼剃根。 笑死,一個(gè)胖子當(dāng)著我的面吹牛前方,可吹牛的內(nèi)容都是我干的狈醉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼惠险,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼苗傅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起班巩,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤金吗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后趣竣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體摇庙,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年遥缕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了卫袒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡单匣,死狀恐怖夕凝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情户秤,我是刑警寧澤码秉,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站鸡号,受9級(jí)特大地震影響转砖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鲸伴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一府蔗、第九天 我趴在偏房一處隱蔽的房頂上張望晋控。 院中可真熱鬧,春花似錦姓赤、人聲如沸痛黎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽啥纸。三九已至,卻和暖如春誓斥,著一層夾襖步出監(jiān)牢的瞬間综看,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工岖食, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人舞吭。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓泡垃,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親羡鸥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蔑穴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法惧浴,內(nèi)部類的語法存和,繼承相關(guān)的語法,異常的語法衷旅,線程的語...
    子非魚_t_閱讀 31,625評(píng)論 18 399
  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 3,811評(píng)論 0 11
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理捐腿,服務(wù)發(fā)現(xiàn),斷路器柿顶,智...
    卡卡羅2017閱讀 134,654評(píng)論 18 139
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉茄袖,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,709評(píng)論 0 9
  • Spark SQL, DataFrames and Datasets Guide Overview SQL Dat...
    Joyyx閱讀 8,328評(píng)論 0 16