C++ 嵌入/调用Python方法 爬取天气网数据Qt:C++ QML Python

基于功能需求,需要得知当前地点的天气状况;项目技术采用QT框架,利用C++集成python,获取python接口解析获取的天气数据,并吐给qml前端显示;

1.步骤一:cmakelist.txt方式构建带界面的qml基础程序,直接主程序通过QQuickView方式构建主界面;(QWindows的方式也行,按自己喜好)

main函数示例: 

2.步骤二:编写python爬取天气网数据(利用requests和BeautifulSoup库);

注意: 若能直接解析天气网主页,触发主页js,应该能够直接获取到本地ip的天气情况;否则建议主页HTML直接ctrl+S,找到存储路径里面的城市对应的id,拼凑成具体城市天气的html,获取数据并解析;(本文主要示例后者)

参考链接:

爬取天气网数据:Python爬取天气数据及可视化分析-python爬取天气数据 (51cto.com)

天气网主页:天气网 (weather.com.cn)

python方法:

import requests
from bs4 import BeautifulSoup

def getHTMLtext(url):
 """请求获得网页内容"""
 try:
  r = requests.get(url, timeout = 30)
  r.raise_for_status()
  r.encoding = r.apparent_encoding
  print("Success")
  return r.text
 except:
  print("Fail")
  return" "

def save(doc,fileName):
 file = open(fileName, 'w',encoding="utf-8")
 file.write(doc)
 file.close()

def parseWeather(strHtml):
    tmpSoup = BeautifulSoup(str(strHtml), 'html.parser')
    day = tmpSoup.find_all("h1")[0].string
    wea = tmpSoup.find_all("p",class_ = "wea")[0].string
    temSoup = BeautifulSoup(str(tmpSoup.find_all("p",class_ = "tem")), 'html.parser')
    hightem = temSoup.find_all("span")[0].string
    lowtem = temSoup.find_all("i")[0].string
    #print("天气信息====>>>",day,wea, ":", hightem,"/",lowtem)
    return str(day+wea+":"+hightem+"/"+lowtem)


#101270101 成都的城市id
def cityHtml(url):
    cityWeatherHtml = getHTMLtext(url)
    citySoup = BeautifulSoup(cityWeatherHtml, 'html.parser')
    h1 = citySoup.find_all("ul", class_="t clearfix")
    soup2 = BeautifulSoup(str(h1), 'html.parser')   #h1 type bs4.element.ResultSet
    weatherList = soup2.find_all("li")
    print("======weather info length:",len(weatherList))
    weatherStrList = []
    for i in weatherList:
        info = parseWeather(str(i))
        weatherStrList.append(info)

    print("======Array:",weatherStrList)    
    print("======type of:",type(weatherStrList))    
    return weatherStrList




#cityHtml("")

3.步骤三:集成python项目到C++中:

1).确保已经安装了python环境;拷贝python环境下的lib、include、dlls目录到项目中,并拷贝带python方法的文件到项目里;我这里使用的是mingW64,所以采用python64的库;

include和libs文件夹编译需要,include中包含python入口的python.h头文件,libs主要包括python的编译链接库python312.lib;

2).CmakeList.txt文件中,链接上include所有头文件,和libs中的lib库(这些库和所有头文件是否全需要这个未作验证,有兴趣的小伙伴可以自行尝试)

3).引入头文件Python.h ,按步骤调用python方法,获取返回值即可

参考链接:

(1).C++调用python: C++调用python的那些坑(详细教程步骤)_c++调用python函数getattrstring失败-CSDN博客

C++调用python脚本 - 知乎 (zhihu.com)

(2).C++获取python返回值:Python + C/C++ 嵌入式编程(1):多维数组Numpy.Array()在Python和C/C++文件间的传递问题_c++ 调用python 传递多维数组-CSDN博客

4).参考代码:

QString WeatherData::doPython(){
    QString toDayWeather = "";

    PyObject* pModule = NULL;
    PyObject* pFunc = NULL;
    PyObject* pArg = NULL;
    Py_SetPythonHome((wchar_t *)(L"./Python/"));//指定python库解释器的路径
    Py_Initialize();//初始化Python

    // 初始化python系统文件路径,保证可以访问到 .py文件
    // python为运行时链接,即weather.py与.exe的相对路径;而不是本文件main.cpp与.py文件的相对路径
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('./')");

    // 调用python文件名,不用写后缀
    pModule = PyImport_ImportModule("weather");
    if( pModule == NULL ){
        qDebug() <<"module not found";
        return toDayWeather;
    }

    // 获取函数
    pFunc = PyObject_GetAttrString(pModule, "cityHtml");
    if( !pFunc || !PyCallable_Check(pFunc)){
        qDebug() <<"not found function add_num";
        return toDayWeather;
    }
    // 构造参数
    pArg = Py_BuildValue("(s)", "http://www.weather.com.cn/weather/101270101.shtml");  //一个字符串参数

    PyObject* pReturn = PyObject_CallObject(pFunc, pArg);


    // 7、接收python计算好的返回值
    // QStringList nResult;
    // i表示转换成int型变量。 s表示转换成string型变量
    // 在这里,最需要注意的是:PyArg_Parse的最后一个参数,必须加上“&”符号
    if(PyList_Check(pReturn)){ //检查是否为List对象
        int sizeOfList = PyList_Size(pReturn);//List对象的大小,这里SizeOfList =

        qDebug() << "=============>  SizeOfList:"<<sizeOfList;

        for(int i = 0; i < sizeOfList; i++){
            PyObject *Item = PyList_GetItem(pReturn, i);//获取List对象中的每一个元素
            char * result;
            PyArg_Parse(Item, "s", &result);//s表示转换成string型变量
            //python字符串转换完是utf8编码,需按需转换目标字符编码
            QString result2 = QString::fromUtf8(result);
            if(i == 0) {
                toDayWeather = result2;
            }

            qDebug() << "=======QString Value:" <<result2;

            //Py_DECREF(Item); //释放空间 #会导致释放崩溃
        }

    }else{
        qDebug() <<"Not a List";
    }

    Py_Finalize(); //释放python接口

    return toDayWeather;
}

注意:PyList_GetItem获取的空间需要手动释放(Py_DECREF),否则会造成内存泄漏;示例中释放导致崩溃,暂未解决;若集成此部分代码,需要考虑解决

4.打包集成:至此,程序若顺利,可以直接在带python环境的机器上编译运行;但需要打包发布,仍需要做一些操作;

1).利用windeployqt打包编译出来的exe所需的qt依赖库;这里暂不赘述,参考本篇文章:QT(qml)程序打包成绿色exe可执行或exe可安装文件(Enigma Virtual Box、Inner SetUp Compiler)_含qml的exe打包-CSDN博客

2).将python依赖,以及python运行环境编译到程序目录中;

说是编译,其实是拷贝到程序构建目录中,并指定执行环境,由于python是运行时链接,所有相对路径需要按照构建出的exe为程序的“当前路径”;

(1).拷贝依赖

示例:这里分别将带"爬虫方法的python文件"、"python312.dll动态库"、"python环境dll和lib"复制到目标路径;

(2).指定环境(上面参考代码中已经指明)

至此,程序构建后,生成的exe打包好QT的依赖,就可以直接双击exe运行了。运行效果截图:

源程序地址:天气预报-爬虫: C++嵌入python模块,python爬取天气数据并解析 1.C++调用python爬虫接口 2.C++qml显示爬虫数据 (gitee.com)

  • 26
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值