Leveraging Industry Sectors for Smarter Value Investing with Python Scraping & FastAPI
This guide explains how to use industry sector classification to support value investing by scraping sector and stock data, parsing JSON responses, filtering by keywords, and exposing the results via FastAPI services, then displaying them in a Uniapp front‑end table for easy stock selection.
1. Industry Sectors
Industry sectors differ from concept stocks; concept stocks are riskier and driven by short‑term news, while industry sectors are classified by stock industry and focus on long‑term stability.
In practice, short‑term selection can use market hotspots and concept stocks, but for medium‑to‑long term investment it is recommended to select stocks based on industry sectors.
2. Scraping sector and stock lists
Using the Toggle JavaScript plugin we discover that sector data comes from a request like http://**/?q=cn|bk|17&n=hqa&c=l&o=pl,d&p=1&_dc=1650680429759. Parameter p is the page number (starting at 1) and _dc is a 13‑digit timestamp.
We then write Python code to fetch the response, extract the sector list with a regular expression, and filter by keyword.
self.ps_url = 'http://**/?q=cn|bk|17&n=hqa&c=l&o=pl,d&p={}&_dc={}'
def __get_timestramp(self):
"""获取13位的时间戳"""
return int(round(time.time() * 1000))
def get_plates_list(self, plate_keyword):
plates = []
index = 0
while True:
url = self.ps_url.format(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("
", ""))
if not result:
break
temp_plate_list = [item for item in result if plate_keyword in item[2]]
index += 1
for item in temp_plate_list:
plates.append({
"name": item[2],
"plate_path": item[1],
"up_or_down": str(item[10]) + "%",
"top_stock": item[-6]
})
return platesSimilarly, stock data for a given sector is obtained from http://**/?q=cn|s|bk{plate_path}&c=m&n=hqa&o=pl,d&p=1&_dc={}. The code extracts stock name, PE, price, and change percentage, then sorts by PE.
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):
stocks = []
index = 0
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("
", ""))
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]) + "%"
})
stocks.sort(key=lambda x: x["pe"])
return stocksBy combining the sector path (e.g., 400128925) with the stock URL template, we can construct URLs such as http://summary.**/hybk/400128925.shtml to retrieve the stock list for a specific sector.
3. Serviceization
We wrap the scraping logic into FastAPI endpoints so that the front‑end can request sector lists and stock lists on demand.
@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:
return fail()
finally:
pstock.teardown()
@app.post("/xag/plate_stock_list")
async def get_plate_stock_list(plateStock: PlateStock):
pstock = PStock()
try:
result = pstock.get_stock_list(plateStock.plate_path)
return success(data=result, message="查询成功!")
except Exception:
return fail()
finally:
pstock.teardown()The front‑end, built with Uniapp, uses a form to submit a sector keyword, calls /xag/plate_list, and displays the returned sectors in a uni-table. Selecting a sector triggers /xag/plate_stock_list to show the stock list with columns for sector name, change percentage, and top stock.
// Simplified Uniapp template
<view class="box">
<uni-forms ref="baseForm" :modelValue="baseFormData" :rules="rules">
<uni-forms-item label="关键字" required name="content">
<uni-easyinput v-model="baseFormData.content" placeholder="板块关键字"/>
</uni-forms-item>
</uni-forms>
<button type="primary" @click="submit('baseForm')">提交</button>
<view class="result" v-show="result.length>0">
<uni-table border stripe emptyText="暂无数据">
<uni-tr class="uni-item">
<uni-th width="100%">板块</uni-th>
<uni-th width="100%">涨跌幅</uni-th>
<uni-th width="100%">强势股</uni-th>
</uni-tr>
<uni-tr v-for="(item, index) in result" :key="index" @row-click="rowclick(item)">
<uni-td>{{ item.name }}</uni-td>
<uni-td>{{ item.up_or_down }}</uni-td>
<uni-td>{{ item.top_stock }}</uni-td>
</uni-tr>
</uni-table>
</view>
</view>After deployment, users can input a sector keyword, retrieve matching sectors, and then view the low‑PE stocks within the chosen sector for potential investment.
4. Summary
Industry sectors are more suitable for medium‑ to long‑term investing; by filtering sectors with a keyword and then sorting the stocks in the sector by low PE, investors can quickly identify attractive candidates.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
