教你用 Python 快速獲取行業(yè)板塊股,輔助價(jià)值投資!

#?1.?行業(yè)板塊
行業(yè)板塊與概念股在定義上還是有很大區(qū)別的
一般來(lái)說(shuō),概念板塊的風(fēng)險(xiǎn)更大,基于某個(gè)消息被短期炒作,很不穩(wěn)定,因此風(fēng)險(xiǎn)更大
行業(yè)板塊是按股票行業(yè)進(jìn)行分類,往往注重于長(zhǎng)期,穩(wěn)定性更高
在實(shí)際投資上,短期可以根據(jù)按「 市場(chǎng)熱點(diǎn)?」從概念股進(jìn)行選股投資,中長(zhǎng)期還是建議按「?行業(yè)板塊?」選股進(jìn)行投資
#?2. 爬取相關(guān)板塊及個(gè)股列表
目標(biāo)對(duì)象:
aHR0cDovL3N1bW1hcnkuanJqLmNvbS5jbi9oeWJrLw==

2-1??板塊列表
首先,我們使用 「 Toggle JavaScript 」插件發(fā)現(xiàn)頁(yè)面中的行業(yè)板塊數(shù)據(jù)來(lái)源于下面的請(qǐng)求結(jié)果
http://**/?q=cn|bk|17&n=hqa&c=l&o=pl,d&p=1020&_dc=1650680429759

其中,參數(shù)為 p 和?_dc 為可變參數(shù),p 代表頁(yè)碼數(shù)(從 1 開(kāi)始),_dc 代表 13 位的時(shí)間戳,其他查詢參數(shù)都是固定內(nèi)容
然后,我們編寫代碼獲取響應(yīng)數(shù)據(jù),使用正則表達(dá)式匹配出行業(yè)列表的數(shù)據(jù)
...
self.ps_url?=?'http://**/?q=cn|bk|17&n=hqa&c=l&o=pl,d&p={}050&_dc={}'
....
????def?__get_timestramp(self):
????????"""
????????獲取13位的時(shí)間戳
????????:return:
????????"""
????????return?int(round(time.time()?*?1000))
...
????def?get_plates_list(self,?plate_keyword):
????????"""
????????獲取所有板塊
????????:return:
????????"""
????????plates?=?[]
????????index?=?0
????????while?True:
????????????url?=?self.ps_url.format(index?+?1,?self.__get_timestramp())
????????????#?解析數(shù)據(jù)
????????????resp?=?self.session.get(url,?headers=self.headers).text
????????????match?=?re.compile(r'HqData:(.*?)};',?re.S)
????????????result?=?json.loads(re.findall(match,?resp)[0].strip().replace("\n",?""))
????????????if?not?result:
????????????????break
????????????#?根據(jù)關(guān)鍵字,過(guò)濾有效板塊
????????????temp_plate_list?=?[item?for?item?in?result?if?plate_keyword?in?item[2]]
????????????index?+=?1
????????????for?item?in?temp_plate_list:
????????????????print(item)
????????????????plates.append({
????????????????????"name":?item[2],
????????????????????"plate_path":?item[1],
????????????????????"up_or_down":?str(item[10])?+?"%",
????????????????????"top_stock":?item[-6]
????????????????})
????????return?plates
...
最后,根據(jù)關(guān)鍵字對(duì)板塊進(jìn)行一次篩選,通過(guò)板塊名、板塊路徑 PATH、板塊漲跌幅、最大貢獻(xiàn)股票名稱重新組裝成一個(gè)列表
注意:通過(guò)分析頁(yè)面發(fā)現(xiàn),根據(jù)板塊路徑 PATH 可以組裝成行業(yè)板塊個(gè)股列表頁(yè)面 URL
比如,行業(yè)板塊 PATH 為 400128925,那么行業(yè)板塊對(duì)應(yīng)個(gè)股列表的頁(yè)面 URL 為
http://summary.**/hybk/400128925.shtml
2-2??行業(yè)個(gè)股列表
爬取行業(yè)個(gè)股列表和上一步數(shù)據(jù)展示邏輯一樣,個(gè)股列表數(shù)據(jù)同樣來(lái)源于下面請(qǐng)求的結(jié)果
http://**/?q=cn|s|bk{}&c=m&n=hqa&o=pl,d&p={}020&_dc={}
其中,bk 后面對(duì)應(yīng)行業(yè)板塊 PATH,p 代表頁(yè)碼數(shù),_dc 代表 13 位的時(shí)間戳
...
#?個(gè)股
self.stock_url?=?'http://**/?q=cn|s|bk{}&c=m&n=hqa&o=pl,d&p={}020&_dc={}'
....
????def?get_stock_list(self,?plate_path):
????????"""
????????獲取某一個(gè)板塊下所有的個(gè)股信息
????????包含:股票名稱、最新價(jià)格、漲跌幅、市盈率
????????:param?plate_info:
????????:return:
????????"""
????????index?=?0
????????stocks?=?[]
????????while?True:
????????????url?=?self.stock_url.format(plate_path,?index?+?1,?self.__get_timestramp())
????????????resp?=?self.session.get(url,?headers=self.headers).text
????????????match?=?re.compile(r'HqData:(.*?)};',?re.S)
????????????result?=?json.loads(re.findall(match,?resp)[0].strip().replace("\n",?""))
????????????if?not?result:
????????????????break
????????????index?+=?1
????????????for?item?in?result:
????????????????if?item[-1]?0:
????????????????????continue
????????????????stocks.append({
????????????????????"stock_name":?item[2],
????????????????????"pe":?item[-1],
????????????????????"price":?item[8],
????????????????????"up_or_down":?str(item[12])?+?"%"
????????????????})
????????#?按pe降序排列
????????stocks.sort(key=lambda?x:?x["pe"])
????????return?stocks通過(guò)正則表達(dá)式對(duì)響應(yīng)結(jié)果進(jìn)行匹配后,獲取個(gè)股的名稱、PE 市盈率、價(jià)格、漲跌幅 4 個(gè)關(guān)鍵數(shù)據(jù)
最后,對(duì)個(gè)股列表按 PE 進(jìn)行升序排列后直接返回
# 3. 服務(wù)化
當(dāng)然,我們可以將這部分邏輯服務(wù)化供前端使用,以此提升用戶的體驗(yàn)性
比如,使用 FastAPI 可以快速創(chuàng)建兩個(gè)服務(wù):根據(jù)關(guān)鍵字獲取行業(yè)板塊列表、根據(jù)板塊路徑獲取個(gè)股列表
from?pydantic?import?BaseModel
#?板塊
class?Plate(BaseModel):
????content:?str??#?關(guān)鍵字
#?板塊下的個(gè)股
class?PlateStock(BaseModel):
????plate_path:?str??#?板塊路徑
#===========================================================
...
#?獲取板塊列表
@app.post("/xag/plate_list")
async?def?get_plate_list(plate:?Plate):
????pstock?=?PStock()
????try:
????????result?=?pstock.get_plates_list(plate.content)
????????return?success(data=result,?message="查詢成功!")
????except?Exception?as?e:
????????return?fail()
????finally:
????????pstock.teardown()
#?獲取某一個(gè)板塊下的所有股票列表
@app.post("/xag/plate_stock_list")
async?def?get_plate_list(plateStock:?PlateStock):
????pstock?=?PStock()
????try:
????????result?=?pstock.get_stock_list(plateStock.plate_path)
????????return?success(data=result,?message="查詢成功!")
????except?Exception?as?e:
????????return?fail()
????finally:
????????pstock.teardown()
...
前端以 Uniapp 為例,使用 uni-table 組件展示行業(yè)板塊列表及個(gè)股列表
部分代碼如下:
//個(gè)股列表?platestock.vue
...
class="box">
????????????????ref="baseForm"?:modelValue="baseFormData"?:rules="rules">
????????????????????"關(guān)鍵字"?required?name="content">
????????????????????????"baseFormData.content"?placeholder="板塊關(guān)鍵字"?/>
????????????????????
????????????????
????????????????
????????????????
????????????????class="result"?v-show="result.length>0">
????????????????????ref="table"?border?stripe?emptyText="暫無(wú)數(shù)據(jù)">
????????????????????????class="uni-item">
????????????????????????????"center"?class="uni-th"?width="100%">板塊
????????????????????????????"center"?class="uni-th"?width="100%">漲跌幅
????????????????????????????"center"?class="uni-th"?width="100%">強(qiáng)勢(shì)股
????????????????????????
????????????????????????class="uni-item"?v-for="(item,?index)?in?result"?:key="index"?@row-click="rowclick(item)">
????????????????????????????class="uni-th"?align="center">{{?item.name?}}
????????????????????????????"center"?class="uni-th">{{?item.up_or_down?}}
????????????????????????????"center"?class="uni-th">{{?item.top_stock?}}
????????????????????????
????????????????????
????????????????
????????????
...
methods:?{
????????????//表單提交數(shù)據(jù)
????????????submit(ref)?{
????????????????this.$refs[ref].validate().then(res?=>?{
????????????????????this.$http('xag/plate_list',?this.baseFormData,?{
????????????????????????hideLoading:?false,
????????????????????????hideMsg:?false,
????????????????????????method:?'POST'
????????????????????}).then(res?=>?{
????????????????????????console.log("內(nèi)容:",?res.data)
????????????????????????if?(res.data?&&?res.data.length?>?0)?{
????????????????????????????this.$tip.success("查詢成功!")
????????????????????????????this.result?=?res.data
????????????????????????}?else?{
????????????????????????????this.$tip.success("查詢結(jié)果為空,請(qǐng)換一個(gè)關(guān)鍵字查詢!")
????????????????????????}
????????????????????}).catch(err?=>?{
????????????????????????console.log("產(chǎn)生異常,異常信息:",?err)
????????????????????})
????????????????}).catch(err?=>?{
????????????????????console.log('err',?err);
????????????????})
????????????}
...最后部署完項(xiàng)目后,在前端頁(yè)面就能根據(jù)板塊名選擇合適的個(gè)股進(jìn)行投資了

# 4. 總結(jié)一下
由于行業(yè)板塊更適用于中長(zhǎng)期投資,我們只需要根據(jù)某一個(gè)關(guān)鍵字篩選出一個(gè)板塊,然后在板塊下的個(gè)股列表中可以非常直觀地看出市盈率較低的個(gè)股進(jìn)行投資即可
我已將文中大部分源碼上傳到后臺(tái),關(guān)注下方公眾號(hào)回復(fù)關(guān)鍵字「 220423?」即可以獲取
如果你覺(jué)得文章還不錯(cuò),請(qǐng)大家?點(diǎn)贊、分享、留言?下,因?yàn)檫@將是我持續(xù)輸出更多優(yōu)質(zhì)文章的最強(qiáng)動(dòng)力!

