上篇文章介绍了如何从网上获取股票数据,下面将介绍如何分析这些数据,要分析首先需要获取更多的数据,在获取所有股票数据之前,需要先获取所有的股票代码。这里用qt做开发,qt在写界面时比较方便,后台数据库用mysql,(当然用其他语言开发也是可以的,思路都是一样的)在开发之前需要先把这个环境搭建好,网上可以找到相关资料,比如https://blog.csdn.net/yy64578537/article/details/71006042 ,装好之后手动创建一个数据库,再创建一个表,比如stocklist,创建一个字段stockNum用来存放股票代码。
下面开始连接数据库,代码如下:
bool stockDialog::connectDb(){
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setPort(3306);
db.setDatabaseName(databaseName);
db.setUserName(userName);
db.setPassword(passWord);
db.setHostName(hostName);
if(!db.open())
{
ui->dbStatus->setText(db.lastError().text());
return false;
}else{
return true;
}
}
返回成功就说明数据库连接成功了,下面获取已有的股票代码,当然首次是空的,这一步为了后续更新股票代码而做。如下:
QStringList stockNumList;
QString sel = QString("select stockNum from stocklist");
bool result = query.exec(sel);
if(result){
while(query.next()){
QString stockNum = query.value(0).toString();
stockNumList<<stockNum;//获取所有股票代码
}
}
下面开始获取新的股票代码,这里用了一种比较笨的方法,因为股票代码是有范围的,比如上证目前的范围都在600000-600400之间,只在这个范围内搜索即可。思想是取请求获取该代码数据,如果有返回值说明该代码是股票代码,写入数据库,否则不是。代码如下:里面的stockSource1是个字符串,和上篇博客中url格式相同。
//更新股票数量
void stockDialog::on_refreshStock_clicked()
{
stockNumList.clear();
QTime startTime = QTime::currentTime();
ui->refreshStatus->setText("正在更新股票数量...");
QSqlQuery query;
QString sel = QString("select stockNum from stocklist");
bool result = query.exec(sel);
if(result){
while(query.next()){
QString stockNum = query.value(0).toString();
stockNumList<<stockNum;//获取所有股票代码
}
}
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager,SIGNAL(finished(QNetworkReply*)),this, SLOT(writeData(QNetworkReply*)));
for(int i=600000;i<604000;i++){//上证范围
if(stockNumList.contains(QString::number(i,10)))
continue;
QNetworkRequest request(stockSource1.arg(i).arg(ui->lastTime->text()).arg(ui->thisTime->text()));
request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/x-www-form-urlencoded");
manager->get(request);
sleep(20);
}
for(int i=300000;i<300999;i++){//创业板范围,后续可能需要加大
if(stockNumList.contains(QString::number(i,10)))
continue;
QNetworkRequest request(stockSource1.arg(i).arg(ui->lastTime->text()).arg(ui->thisTime->text()));
request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/x-www-form-urlencoded");
manager->get(request);
sleep(20);
}
for(int i=1600;i<2999;i++){
QString ii = "00"+QString::number(i, 10);
if(stockNumList.contains(ii))
continue;
QNetworkRequest request(stockSource1.arg(ii).arg(ui->lastTime->text()).arg(ui->thisTime->text()));
request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/x-www-form-urlencoded");
manager->get(request);
sleep(20);
}
for(int i=100;i<1000;i++){
QString ii = "000"+QString::number(i, 10);
if(stockNumList.contains(ii))
continue;
QNetworkRequest request(stockSource1.arg(ii).arg(ui->lastTime->text()).arg(ui->thisTime->text()));
request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/x-www-form-urlencoded");
manager->get(request);
sleep(20);
}
for(int i=10;i<100;i++){
QString ii = "0000"+QString::number(i, 10);
if(stockNumList.contains(ii))
continue;
QNetworkRequest request(stockSource1.arg(ii).arg(ui->lastTime->text()).arg(ui->thisTime->text()));
request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/x-www-form-urlencoded");
manager->get(request);
sleep(20);
}
for(int i=1;i<10;i++){
QString ii = "00000"+QString::number(i, 10);
if(stockNumList.contains(ii))
continue;
QNetworkRequest request(stockSource1.arg(ii).arg(ui->lastTime->text()).arg(ui->thisTime->text()));
request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/x-www-form-urlencoded");
manager->get(request);
sleep(20);
}
QTime stopTime = QTime::currentTime();
int elapsed = startTime.msecsTo(stopTime)/1000;
QString str = "更新股票数量结束,用时"+QString::number(elapsed, 10)+"秒";
ui->refreshStatus->setText(str);
stockNumList.clear();
result = query.exec(sel);
if(result){
while(query.next()){
QString stockNum = query.value(0).toString();
stockNumList<<stockNum;//获取所有股票代码
}
}
}
上面的槽函数writeData如下:
void stockDialog::writeData(QNetworkReply* reply){
QTextCodec *codec = QTextCodec::codecForName("utf8");
QByteArray responseData = codec->toUnicode(reply->readAll()).toLatin1();
//qDebug() << responseData.size();
for(int i=0;i<responseData.length();++i){
if(responseData.at(i)=='{'){
responseData.remove(0,i);
}
}
//qDebug() << responseData.size();
for(int i=responseData.length()-1;i>0;--i){
if(responseData.at(i)=='}'){
responseData.remove(i+1,responseData.length()-1);
}
}
qDebug() << responseData.size();
QJsonParseError jsonError;
QJsonDocument doucment = QJsonDocument::fromJson(responseData, &jsonError); // 转化为 JSON 文档
if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) { // 解析未发生错误
if (doucment.isObject()) { // JSON 文档为对象
QJsonObject object = doucment.object(); // 转化为对象
if (object.contains("status")) {
QJsonValue value = object.value("status");
if (value.isDouble()) {
int nFrom = value.toVariant().toInt();
qDebug() << "From : " << nFrom;
if(nFrom==0){
if (object.contains("status")) {
QJsonValue value2 = object.value("code");
QString val = value2.toString().mid(3,7);
QSqlQuery query;
QString sel = QString("select stockNum from stocklist where stockNum = '%1'").arg(val);
bool result = query.exec(sel);
if(result){
if(query.next()){
return;
}else{
QString str = QString("insert into stocklist (stockNum,stockName,stockType) "
"value('%1',2,1)").arg(val);
result = query.exec(str);
}
}
}
}
}
}
}
}
}
这种方法效率还在可接受范围之内,五天数据更新所有股票代码大约需要一分多钟时间。至此,就获取到了所有股票数据,以后可以每隔一段时间更新一下,因为有些新股发售,停牌股票的复牌,股票数量会越来越多的。
如有问题可关注以下公众号并留言:阿兴啊,更多内容将在公众号发布,我们一起探讨学习。