Python安全采集同花顺个股列表及详细页面
一.需要采集的页面是涨跌幅排行_数据中心_同花顺财经所有上市公司股票信息,以及所属概念板块。使用Edge浏览器进行采集。
二.检查页面
1.进入页面涨跌幅排行_数据中心_同花顺财经,按F12打开检查。
2.进入检查后,先点击网络(第1步),这时候下方应该会刷新出“1/”,如果没有刷新出来,就点击左下方第一页(第2步),此时就会刷新出来。然后打开“1/”(第3步)。
3.打开“1/”后,可以找到相关URL、请求标头、响应标头等信息,重点看黄色框标注的信息,在采集程序时要配置这些参数。之后进行代码的编写。

三.试着先采集第一页内容看看
1.导入库
import requests
import parsel
from lxml import etree
import time
import random
import execjs
import pandas as pd
import pickle
2.配置URL、请求头参数。
新建三个变量headers、url、page_cookie,将在检查中找到的内容对号入座赋值给三个变量。
headers = {
"User-Agent": "************************************************************",
"Accept-Encoding": "gzip, deflate, br",
}
url = f"https://data.10jqka.com.cn/market/zdfph/field/zdf/order/desc/ajax/1/free/1/page/1/free/1/"
page_cookie = {
"v": "A3qivkkdxq0YZUrBCY0TqtC5y6uZK_gvcK5ypoRzJz3anxSVbLtOFUA_wrpX"
}
3.尝试发送请求,并打印获取到的html。
session = requests.Session()
response = session.get(url = url, headers = headers, cookies = page_cookie, timeout = 10, verify = False)
response.encoding = "gbk"
html = response.text
print(html)
4.与个股相关的内容如下,内容太长了,所以只演示一只股票。
<tr >
<td class="first tc">4</td>
<td class="tc "><a href="http://stockpage.10jqka.com.cn/300801/" target="_blank">300801</a></td>
<td class="tc"><a href="http://stockpage.10jqka.com.cn/300801/" target="_blank" code="hs_300801" class="J_showCanvas">泰和科技</a></td>
<td class="tr c-rise ">20.90</td>
<td class="tr c-rise cur">15.92</td>
<td class="tr c-rise ">23.30</td>
<td class="tr c-rise ">22.49</td>
<td class="tr c-rise ">22.80</td>
<td class="tr c-rise ">46.27</td>
<td class="tr c-rise ">50.49</td>
<td class="tr c-fall ">-793.91万</td>
<td class="tr c-rise ">4986.50万</td>
<td class="tr c-rise ">4963.21万</td>
</tr>
4.因为所有与个股相关的部分都在子节点下,使用xpath对子节点的内容进行解析。
html_tree = etree.HTML(html)
stock_list = html_tree.xpath("//table[@class='m-table J-ajax-table']/tbody/tr")
5.获得所有子节点,并存放在变量stock_list中。
[<Element tr at 0x2312fab9100>,
<Element tr at 0x2312fab8e40>,
<Element tr at 0x2312fab8ec0>,
<Element tr at 0x2312fab9140>,
<Element tr at 0x2312fab91c0>,
<Element tr at 0x2312fab9400>,
<Element tr at 0x2312fab9240>,
<Element tr at 0x2312fab9440>,
<Element tr at 0x2312fab93c0>,
<Element tr at 0x2312fab8f40>,
<Element tr at 0x2312fab9340>,
<Element tr at 0x2312fab92c0>,
<Element tr at 0x2312fab9300>,
<Element tr at 0x2312fab9480>,
<Element tr at 0x2312fab9640>,
<Element tr at 0x2312fab8800>,
<Element tr at 0x2312fab8e00>,
<Element tr at 0x2312fab95c0>,
<Element tr at 0x2312fab99c0>,
<Element tr at 0x2312fab9580>,
<Element tr at 0x2312fab98c0>,
<Element tr at 0x2312fab9940>,
<Element tr at 0x2312fab9a00>,
<Element tr at 0x2312fab9a40>,
<Element tr at 0x2312fab9a80>,
...
<Element tr at 0x2312fab8640>,
<Element tr at 0x2312fab9f40>,
<Element tr at 0x2312fab9600>,
<Element tr at 0x2312fab8f00>,
<Element tr at 0x2312fab9f80>]
6.进一步解析每个,以获得个股代码以及股票简称,将解析出的内容存入列表stock。
stocks = []
for stock in stock_list:
# 从列表中获取第一个元素,如果列表为空则返回None
code = stock.xpath(".//td[2]/a/text()")
code = code[0] if code else None
name = stock.xpath(".//td[3]/a/text()")
name = name[0] if name else None
# 存储为字典
stocks.append({
"代码": code,
"简称": name
})
7.列表stock。
[{'代码': '301421', '简称': '波长光电'},
{'代码': '300515', '简称': '三德科技'},
{'代码': '300172', '简称': '中电环保'},
{'代码': '300801', '简称': '泰和科技'},
{'代码': '301219', '简称': '腾远钴业'},
{'代码': '301176', '简称': '逸豪新材'},
{'代码': '300072', '简称': '海新能科'},
{'代码': '300531', '简称': '优博讯'},
{'代码': '301003', '简称': '江苏博云'},
{'代码': '301213', '简称': '观想科技'},
{'代码': '300157', '简称': '新锦动力'},
{'代码': '300240', '简称': '飞力达'},
{'代码': '688010', '简称': '福光股份'},
{'代码': '300875', '简称': '捷强装备'},
{'代码': '600798', '简称': '宁波海运'},
{'代码': '600844', '简称': '丹化科技'},
{'代码': '600794', '简称': '保税科技'},
{'代码': '600698', '简称': '湖南天雁'},
{'代码': '000637', '简称': '茂化实华'},
{'代码': '601008', '简称': '连云港'},
{'代码': '002278', '简称': '神开股份'},
{'代码': '300618', '简称': '寒锐钴业'},
{'代码': '601022', '简称': '宁波远洋'},
{'代码': '003026', '简称': '中晶科技'},
{'代码': '600610', '简称': '中毅达'},
...
{'代码': '000547', '简称': '航天发展'},
{'代码': '000881', '简称': '中广核技'},
{'代码': '600800', '简称': '渤海化学'},
{'代码': '002109', '简称': '兴化股份'},
{'代码': '000892', '简称': '欢瑞世纪'}]
第一页的所有股票信息可以成功采集,接下来实现自动翻页采集。
四.翻页采集。
1.动态生成url参数。
每一页的url地址都会发生变化,例如:
第一页的url地址是
"https://data.10jqka.com.cn/market/zdfph/field/zdf/order/desc/ajax/1/free/1/page/1/free/1/"
第二页的url地址是
"https://data.10jqka.com.cn/market/zdfph/field/zdf/order/desc/ajax/1/free/1/page/2/free/1/"
会发现url只有页数的数字改变了。因此需要动态生成url。
page = 2
headers = {
"User-Agent": "********************************************************************************************************",
"Accept-Encoding": "gzip, deflate, br",
}
url = f"https://data.10jqka.com.cn/market/zdfph/field/zdf/order/desc/ajax/1/free/1/page/{page}/free/1/"
page_cookie = {
"v": "A3qivkkdxq0YZUrBCY0TqtC5y6uZK_gvcK5ypoRzJz3anxSVbLtOFUA_wrpX"
}
session = requests.Session()
response = session.get(url = url, headers = headers, cookies = page_cookie, timeout = 10, verify = False)
response.encoding = "gbk"
html = response.text
html_tree = etree.HTML(html)
stock_list = html_tree.xpath("//table[@class='m-table J-ajax-table']/tbody/tr")
结果发现得到的stock_list是空列表:
[]
这是因为当每次刷新页面时浏览器都会自动更新cookie,生成新的cookie,当硬编码cookie时就采集不到数据了,因此要想正确采集,需要做的是通过模拟浏览器的行为来动态生成cookie。
2.动态生成cookie。
需要模拟浏览器动态生成cookie,因此需要知道cookie生成的函数以及位置。
(1).首先我们需要找到cookie生成的程序的位置。点击源代码(第1步),新建一个新片段(第2步),植入hook程序(第3步),并执行程序(第4步)。

此时右侧会出现“调用堆栈”,从上往下点,直到找到生成cookie的函数位置。
(2).在本地新建一个js文件,取名“cookie_update_2.js”,然后将chameleon文件里的内容全部复制到“cookie_update_2.js”文件中。
(3).补环境。
document = {
documentElement:{}
};
window = global;
navigator = {
plugins:{},
userAgent:****************************
}
head = {}
div = {}
location = {
href:'https://data.10jqka.com.cn/market/zdfph/',
protocol:'https:',
hostname:'data.10jqka.com.cn',
host:'data.10jqka.com.cn'
}
Element = {
protocol:{}
}
null_function = function(){
console.log(arguments)
}
getElementsByTagName = function(val){
if(val==="head"){
return [head]
}
}
createElement = function(val){
if(val==="div"){
return div
}
}
addEventListener = null_function
window.XMLHttpRequest = null_function
window.ActiveXObject = null_function
navigator.javaEnabled = null_function
document.addEventListener = addEventListener
document.createElement = createElement
document.getElementsByTagName = getElementsByTagName
setInterval = function(){}
var loc_v;
//网站原码
...
//
cookie_v = loc_v()
console.log(cookie_v)
(4).将cookie_update_2.js植入程序,并动态更新cookie。
js_file = open("cookie_update_2.js", encoding = "utf-8").read()
js_code = execjs.compile(js_file)
v = js_code.call("loc_v")
page_cookie = {
"v":v
}
3.采集数据,并打印结果。
page = 2
js_file = open("cookie_update_2.js", encoding = "utf-8").read()
js_code = execjs.compile(js_file)
v = js_code.call("loc_v")
page_cookie = {
"v":v
}
headers = {
"User-Agent": ***********************************************,
"Accept-Encoding": "gzip, deflate, br",
}
url = f"https://data.10jqka.com.cn/market/zdfph/field/zdf/order/desc/ajax/1/free/1/page/{page}/free/1/"
session = requests.Session()
response = session.get(url = url, headers = headers, cookies = page_cookie, timeout = 10, verify = False)
response.encoding = "gbk"
html = response.text
print(html)
html_tree = etree.HTML(html)
stock_list = html_tree.xpath("//table[@class='m-table J-ajax-table']/tbody/tr")
stocks = []
for stock in stock_list:
# 从列表中获取第一个元素,如果列表为空则返回None
code = stock.xpath(".//td[2]/a/text()")
code = code[0] if code else None
name = stock.xpath(".//td[3]/a/text()")
name = name[0] if name else None
# 存储为字典
stocks.append({
"代码": code,
"简称": name
})
print(stocks)
打印结果:
[{'代码': '000554', '简称': '泰山石油'},
{'代码': '600201', '简称': '生物股份'},
{'代码': '002490', '简称': '山东墨龙'},
{'代码': '603022', '简称': '新通联'},
{'代码': '603578', '简称': '三星新材'},
{'代码': '603928', '简称': '兴业股份'},
{'代码': '002040', '简称': '南京港'},
{'代码': '000547', '简称': '航天发展'},
{'代码': '000881', '简称': '中广核技'},
{'代码': '600800', '简称': '渤海化学'},
{'代码': '002753', '简称': '永东股份'},
{'代码': '002109', '简称': '兴化股份'},
{'代码': '000892', '简称': '欢瑞世纪'},
{'代码': '688638', '简称': '誉辰智能'},
{'代码': '688010', '简称': '福光股份'},
{'代码': '688230', '简称': '芯导科技'},
{'代码': '300875', '简称': '捷强装备'},
{'代码': '000584', '简称': '工智退'},
{'代码': '688371', '简称': '菲沃泰'},
{'代码': '300584', '简称': '海辰药业'},
{'代码': '300541', '简称': '先进数通'},
{'代码': '300164', '简称': '通源石油'},
{'代码': '300301', '简称': '*ST长方'},
{'代码': '301379', '简称': '天山电子'},
{'代码': '002207', '简称': '准油股份'},
...
{'代码': '300740', '简称': '水羊股份'},
{'代码': '600470', '简称': '六国化工'},
{'代码': '001205', '简称': '盛航股份'},
{'代码': '601718', '简称': '际华集团'},
{'代码': '002449', '简称': '国星光电'}]
4.自动翻页采集。
同理,每当翻下一页,cookie都要重新更新。同时加入延时采集,加入异常处理。
pages = 103
headers = {
"User-Agent": ***************************************,
"Accept-Encoding": "gzip, deflate, br",
}
stocks = []
for page in range(1, pages + 1):
js_file = open("cookie_update_2.js", encoding = "utf-8").read()
js_code = execjs.compile(js_file)
v = js_code.call("loc_v")
page_cookie = {
"v":v
}
print("正在采集第", page, "页...")
url = f"https://data.10jqka.com.cn/market/zdfph/field/zdf/order/desc/ajax/1/free/1/page/{page}/free/1/"
session = requests.Session()
for attempt in range(3):
try:
# session.get(url = "https://data.10jqka.com.cn/", headers = headers)
response = session.get(url = url, headers = headers, cookies = page_cookie, timeout = 10, verify = False)
except TimeoutError as e:
print(f"第{page}页 请求超时...")
except ConnectionError as e:
print(f"第{page}页 连接错误...")
except ConnectionRefusedError as e:
print(f"第{page}页 请求异常...")
except Exception as e:
print(e)
else:
print(f"第{page}页 第{attempt + 1}次获取成功...")
break
wait_time = 5 * (2 ** attempt) # 指数退避策略
print(f"等待 {wait_time} 秒后重试...")
time.sleep(wait_time)
response.encoding = "gbk"
html = response.text
html_tree = etree.HTML(html)
stock_list = html_tree.xpath("//table[@class='m-table J-ajax-table']/tbody/tr")
for stock in stock_list:
# 从列表中获取第一个元素,如果列表为空则返回None
code = stock.xpath(".//td[2]/a/text()")
code = code[0] if code else None
name = stock.xpath(".//td[3]/a/text()")
name = name[0] if name else None
# 存储为字典
stocks.append({
"代码": code,
"简称": name,
})
time.sleep(random.uniform(1, 3))
df_stocks = pd.DataFrame(stocks)
五.对个股详细页面的内容进行采集。

关于个股的详细信息,例如:所属板块概念、主营业务、上市日期等等并不会展示在股票列表中,需要点进个股页面去采集。
- 设置参数。
当点进个股页面以后,复制这一步只需要设置新的url就可以了,cookie可以硬编码。复制搜索框里的地址,动态更新url地址。
code = "000001"
url = f"https://stockpage.10jqka.com.cn/{code}/"
2.采集个股页面中的“涉及概念”。
code = "000001"
headers = {
"User-Agent": **********************************,
"Accept-Encoding": "gzip, deflate, br",
}
v = "A9wERLvD2L-dXazjU9fdYIKvrfGLVYB_AvmUQ7bd6EeqAXKv3mVQD1IJZNAF"
stock_cookie = {
"v":v
}
print("正在采集", code, "的概念")
url = f"https://stockpage.10jqka.com.cn/{code}/"
try:
response = session.get(url = url, headers = headers, cookies = stock_cookie, timeout = 10, verify = False)
except TimeoutError as e:
print(f"获取{stock} 请求超时...")
except ConnectionError as e:
print(f"获取{stock} 连接错误...")
except ConnectionRefusedError as e:
print(f"获取{stock} 请求异常...")
except Exception as e:
print(e)
response.encoding = "utf-8"
html = response.text
print(html)
<dl class="company_details">
<!-- <dt>公司名称:</dt>
<dd>平安银行</dd> -->
<dt>所属地域:</dt>
<dd>广东省</dd>
<dt>涉及概念:</dt>
<dd title="高股息精选,跨境支付(CIPS),深股通,证金持股,融资融券">高股息精选,跨境支付(CIPS)...</dd>
<dt>主营业务:</dt>
<dd><a href="/000001/operate/" target="_blank" class="jyfx stat" stat="f10_spgd_jyfx">经营分析</a></dd>
<dd title=" 办理人民币存、贷、结算、汇兑业务;人民币票据承兑和贴现;各项信托业务;经监管机构批准发行或买卖人民币有价证券;发行金融债券;代理发行、代理兑付、承销政府债券;买卖政府债券;外汇存款、汇款;境内境外借款;从事同业拆借;外汇借款;外汇担保;在境内境外发行或代理发行外币有价证券;买卖或代客买卖外汇及外币有价证券、自营外汇买卖;贸易、非贸易结算;办理国内结算;国际结算;外币票据的承兑和贴现;外汇贷款;资信调查、咨询、见证业务;保险兼业代理业务;代理收付款项;黄金进口业务;提供信用证服务及担保;提供保管箱服务;外币兑换;结汇、售汇;信用卡业务;经有关监管机构批准或允许的其他业务。">办理人民币存、贷、结算、汇兑业务;人民币票据...</dd>
<dt>上市日期:</dt>
<dd>1991-04-03</dd>
<dt>每股净资产:</dt>
<dd>22.48元</dd>
<dt>每股收益:</dt>
<dd>0.62元</dd>
<dt>净利润:</dt>
<dd>140.96亿元</dd>
<dt>净利润增长率:</dt>
<dd>-5.60%</dd>
<dt>营业收入:</dt>
<dd>337.09亿元</dd>
<dt>每股现金流:</dt>
<dd>8.40元</dd>
<dt>每股公积金:</dt>
<dd>4.16元</dd>
<dt>每股未分配利润:</dt>
<dd>13.17元</dd>
<dt>总股本:</dt>
<dd>194.06亿</dd>
<dt>流通股:</dt>
<dd>194.06亿</dd>
</dl>
3.解析html。
html_tree = etree.HTML(html)
concept = html_tree.xpath("//dt[text()='涉及概念:']/following-sibling::dd[1]/@title")
print(code, "的概念是:", concept, "\n")
采集成功:
正在采集 000001 的概念
000001 的概念是: ['高股息精选,跨境支付(CIPS),深股通,证金持股,融资融券']
六.完整过程。
为了实现自动翻页采集股票列表,并且采集每个股票页面的“所属概念”,只需要将以上过程组合在一起就可以实现了。
pages = 103
headers = {
"User-Agent": ******************************************,
"Accept-Encoding": "gzip, deflate, br",
}
stocks = []
for page in range(1, pages + 1):
js_file = open("cookie_update_2.js", encoding = "utf-8").read()
js_code = execjs.compile(js_file)
v = js_code.call("loc_v")
page_cookie = {
"v":v
}
print("正在采集第", page, "页...")
url = f"https://data.10jqka.com.cn/market/zdfph/field/zdf/order/desc/ajax/1/free/1/page/{page}/free/1/"
session = requests.Session()
for attempt in range(3):
try:
# session.get(url = "https://data.10jqka.com.cn/", headers = headers)
response = session.get(url = url, headers = headers, cookies = page_cookie, timeout = 10, verify = False)
except TimeoutError as e:
print(f"第{page}页 请求超时...")
except ConnectionError as e:
print(f"第{page}页 连接错误...")
except ConnectionRefusedError as e:
print(f"第{page}页 请求异常...")
except Exception as e:
print(e)
else:
print(f"第{page}页 第{attempt + 1}次获取成功...")
break
wait_time = 5 * (2 ** attempt) # 指数退避策略
print(f"等待 {wait_time} 秒后重试...")
time.sleep(wait_time)
response.encoding = "gbk"
html = response.text
html_tree = etree.HTML(html)
stock_list = html_tree.xpath("//table[@class='m-table J-ajax-table']/tbody/tr")
for stock in stock_list:
# 从列表中获取第一个元素,如果列表为空则返回None
code = stock.xpath(".//td[2]/a/text()")
code = code[0] if code else None
name = stock.xpath(".//td[3]/a/text()")
name = name[0] if name else None
# 提取概念
v = "A9wERLvD2L-dXazjU9fdYIKvrfGLVYB_AvmUQ7bd6EeqAXKv3mVQD1IJZNAF"
stock_cookie = {
"v":v
}
print("正在采集", name, "的概念")
url = f"https://stockpage.10jqka.com.cn/{code}/"
# session = requests.Session()
# session.get(url = "https://data.10jqka.com.cn/", headers = headers)
try:
response = session.get(url = url, headers = headers, cookies = stock_cookie, timeout = 10, verify = False)
except TimeoutError as e:
print(f"获取{stock} 请求超时...")
except ConnectionError as e:
print(f"获取{stock} 连接错误...")
except ConnectionRefusedError as e:
print(f"获取{stock} 请求异常...")
except Exception as e:
print(e)
response.encoding = "utf-8"
html = response.text
html_tree = etree.HTML(html)
concept = html_tree.xpath("//dt[text()='涉及概念:']/following-sibling::dd[1]/@title")
print(name, "的概念是:", concept, "\n")
# 存储为字典
stocks.append({
"代码": code,
"简称": name,
"涉及概念": concept
})
time.sleep(random.uniform(1, 3))
df_stocks = pd.DataFrame(stocks)
执行结果:
正在采集第 1 页...
第1页 第1次获取成功...
正在采集 新恒汇 的概念
新恒汇 的概念是: ['融资融券,注册制次新股,新股与次新股,人工智能,物联网,专精特新,芯片概念']
正在采集 华之杰 的概念
华之杰 的概念是: ['融资融券,注册制次新股,新股与次新股,消费电子概念,人民币贬值受益']
正在采集 深水规院 的概念
深水规院 的概念是: ['抽水蓄能,物业管理,物联网,数字孪生,华为概念,PPP概念,智慧政务,乡村振兴,国企改革,新型城镇化,地下管网,污水处理,融资融券,粤港澳大湾区,水利,深圳国企改革']
正在采集 强力新材 的概念
强力新材 的概念是: ['PCB概念,芯片概念,先进封装,专精特新,富媒体,融资融券,光刻胶,深股通,OLED'] ...
...
更多推荐




所有评论(0)