基于Request+bs4-re技术路线实现股票数据定向爬虫

  • 一、功能描述
    • 1. 目标
    • 2. 可行性分析
    • 3. 技术路线选择
    • 4. 项目的技术难点
  • 二、程序结构设计
  • 三、程序整体框架
  • 四、程序功能的实现
  • 五、程序的优化
  • 六、代码的进一步优化
  • 七、心得体会
  • 八、参考资料

一、功能描述

1. 目标

获取上交所和深交所所有股票的名称和交易信息,并保存到txt文件中。

2. 可行性分析

  1. 查看网页源代码,看所需要的信息是否在HTML源代码中,非js代码生成,从而选择不同的技术路线。
  2. 查看相应的根目录下的/robots.txt协议,查看允许爬取的权限,以及是否需要伪装成浏览器。
  3. 不要纠结于某个网站,多找信息源尝试
    经过分析,新浪股票网是使用的js生成的,而百度股票网是静态的,所以选择爬取百度股票网上股票数据。
    然后股票的列表我们从东方财富网获得。
    从而确定了数据源:
    获取股票列表:
    东方财富网:http://quote.eastmoney.com/stocklist.html
    获取个股信息:
    百度股票:https://gupiao.baidu.com/stock/
    单个股票:https://gupiao.baidu.com/stock/sz002439.html

3. 技术路线选择

根据前面的分析,以及目前掌握的技术,所以采用requests+bs4+re的技术路线进行实现。

4. 项目的技术难点

  1. 分析确定数据源
  2. 提取股票列表的数据
  3. 提取单个股票信息的数据
  4. 数据的存储方式

二、程序结构设计

Step1:从东方财富网获取股票列表——getHTMLText() getStockList(lst,stockURL)
Step2:根据股票列表逐个到百度股票获取个股信息——getStockInfo(lst,stockURL,fpath)
Step3:将结果存储到文件

三、程序整体框架

写出程序的框架

import requests
from bs4 import BeautifulSoup
import traceback
import redef getHTMLText(url):return ""def getStockList(lst, stockURL):return ""def getStockInfo(lst, stockURL, fpath):return ""def main():passmain()

四、程序功能的实现

实现每一个函数的功能,使得程序能够运行得到我们想要的结果。

#!/usr/bin/env python
#-*- coding:utf-8 -*-import requests
from bs4 import BeautifulSoup
import re
import traceback # 追踪,便于调试def getHTMLText(url): # 获取网页内容try:r = requests.get(url)r.raise_for_status()r.encoding = r.apparent_encodingreturn r.textexcept:return ""def getStockList(lst,stockURL): # 获取股票列表html = getHTMLText(stockURL)soup = BeautifulSoup(html,"html.parser")a = soup.find_all('a') # 需要的股票代码在a标签的“href"属性的值,故先获取全部a标签的列表for i in a:try:href = i.attrs['href'] # q取“href"属性的值lst.append(re.findall(r"s[hz]\d{6}",href)[0]) # 利用正则表达式提取股票代码except: # 因为有的a标签没有股票代码,可以作为异常continuedef getStockInfo(lst,stockURL,fpath): # 获得每只个股的股票信息for stock in lst:url = stockURL + stock + ".html" # 构建爬取股票信息的URLhtml = getHTMLText(url) # 获取股票信息网页内容try:if html == "": # 有些网址打不开,或为空,则跳过continueinfoDict = {} # 以字典的形式保存股票信息,方便后面数据分析soup = BeautifulSoup(html,"html.parser")stockInfo = soup.find('div',attrs = {'class':'stock-bets'}) # 获取股票信息所在的标签name = stockInfo.find_all(attrs={'class':'bets-name'})[0] # 获取股票所在标签,这里注意find_all()返回的是一个bs4.element.ResultSet# 不能用name.string,原因是这里的name标签内有两个字符串子项,所以返回None,详情参照help文档infoDict.update({'股票名称': name.text.split()[0]}) # 通过text以字符串形式获得name标签的所有字符串子项,然后用split()方法通过空格分隔字符串,提取股票名称# 获取其它的键值对信息keyList = stockInfo.find_all('dt') # 键在dt标签valueList = stockInfo.find_all('dd') # 值在dd标签for i in range(len(keyList)): key = keyList[i].text # 这里可以用keyList[i].string,获取键信息val = valueList[i].text # 获取值信息infoDict[key] = val # 往字典中添加键值对with open(fpath, 'a', encoding='utf-8') as f:# 以追加模式打开,因为有中文所以用utf-8编码f.write( str(infoDict) + '\n' ) # 这里为了输出美观,加了一个换行符except:traceback.print_exc() # 追踪错误,便于调试continuedef main():stock_list_url = "http://quote.eastmoney.com/stocklist.html"stock_info_url = "https://gupiao.baidu.com/stock/"output_file = "D://BaiduStockInfo.txt"slist = []getStockList(slist,stock_list_url)getStockInfo(slist,stock_info_url,output_file)main()

程序报错:

分析错误代码,提示属性错误,None类型没有find_all属性,解决方案:定位到Alt+G定位到40行,做一个条件判断,排除None类型的情况。
更正后代码如下:

#!/usr/bin/env python
#-*- coding:utf-8 -*-import requests
from bs4 import BeautifulSoup
import re
import traceback # 追踪,便于调试def getHTMLText(url): # 获取网页内容try:r = requests.get(url)r.raise_for_status()r.encoding = r.apparent_encodingreturn r.textexcept:return ""def getStockList(lst,stockURL): # 获取股票列表html = getHTMLText(stockURL)soup = BeautifulSoup(html,"html.parser")a = soup.find_all('a') # 需要的股票代码在a标签的“href"属性的值,故先获取全部a标签的列表for i in a:try:href = i.attrs['href'] # q取“href"属性的值lst.append(re.findall(r"s[hz]\d{6}",href)[0]) # 利用正则表达式提取股票代码except: # 因为有的a标签没有股票代码,可以作为异常continuedef getStockInfo(lst,stockURL,fpath): # 获得每只个股的股票信息for stock in lst:url = stockURL + stock + ".html" # 构建爬取股票信息的URLhtml = getHTMLText(url) # 获取股票信息网页内容try:if html == "": # 有些网址打不开,或为空,则跳过continueinfoDict = {} # 以字典的形式保存股票信息,方便后面数据分析soup = BeautifulSoup(html,"html.parser")stockInfo = soup.find('div',attrs = {'class':'stock-bets'}) # 获取股票信息所在的标签,有可能部分网页丢失,所以要做类型判断if stockInfo: # stockInfo非None才执行name = stockInfo.find_all(attrs={'class':'bets-name'})[0] # 获取股票所在标签,这里注意find_all()返回的是一个bs4.element.ResultSet# 不能用name.string,原因是这里的name标签内有两个字符串子项,所以返回None,详情参照help文档infoDict.update({'股票名称': name.text.split()[0]}) # 通过text以字符串形式获得name标签的所有字符串子项,然后用split()方法通过空格分隔字符串,提取股票名称# 获取其它的键值对信息keyList = stockInfo.find_all('dt') # 键在dt标签valueList = stockInfo.find_all('dd') # 值在dd标签for i in range(len(keyList)): key = keyList[i].text # 这里可以用keyList[i].string,获取键信息val = valueList[i].text # 获取值信息infoDict[key] = val # 往字典中添加键值对with open(fpath, 'a', encoding='utf-8') as f:# 以追加模式打开,因为有中文所以用utf-8编码f.write( str(infoDict) + '\n' ) # 这里为了输出美观,加了一个换行符except:traceback.print_exc() # 追踪错误,便于调试continuedef main():stock_list_url = "http://quote.eastmoney.com/stocklist.html"stock_info_url = "https://gupiao.baidu.com/stock/"output_file = "D://BaiduStockInfo.txt"slist = []getStockList(slist,stock_list_url)getStockInfo(slist,stock_info_url,output_file)main()

程序正常执行, 但是不显示进度,很慢,打开结果文件部分数据如下:

五、程序的优化

上面的代码初步实现了功能,但是很多代码还有待完善。依旧从性能和用户体验两个方面优化代码。以下是嵩天老师的优化。
从性能上:

  1. r.encoding = r.apparent_encoding,每次获取一次页面,都需要分析整个网页的内容,重复分析,造成了浪费。因为只有两个网址,可以直接在控制台分析其编码方式,然后代码中直接赋值。
    从用户体验上:
    实现能够直观的看到下载的进度。
#!/usr/bin/env python
#-*- coding:utf-8 -*-import requests
from bs4 import BeautifulSoup
import re
import traceback # 追踪,便于调试def getHTMLText(url,code="utf-8"): # 获取网页内容try:r = requests.get(url)r.raise_for_status()r.encoding = codereturn r.textexcept:return ""def getStockList(lst,stockURL): # 获取股票列表html = getHTMLText(stockURL,"GB2312")soup = BeautifulSoup(html,"html.parser")a = soup.find_all('a') # 需要的股票代码在a标签的“href"属性的值,故先获取全部a标签的列表for i in a:try:href = i.attrs['href'] # q取“href"属性的值lst.append(re.findall(r"s[hz]\d{6}",href)[0]) # 利用正则表达式提取股票代码except: # 因为有的a标签没有股票代码,可以作为异常continuedef getStockInfo(lst,stockURL,fpath): # 获得每只个股的股票信息count = 0for stock in lst:url = stockURL + stock + ".html" # 构建爬取股票信息的URLhtml = getHTMLText(url) # 获取股票信息网页内容try:if html == "": # 有些网址打不开,或为空,则跳过continueinfoDict = {} # 以字典的形式保存股票信息,方便后面数据分析soup = BeautifulSoup(html,"html.parser")stockInfo = soup.find('div',attrs = {'class':'stock-bets'}) # 获取股票信息所在的标签,有可能部分网页丢失,所以要做类型判断if stockInfo: # stockInfo非None才执行name = stockInfo.find_all(attrs={'class':'bets-name'})[0] # 获取股票所在标签,这里注意find_all()返回的是一个bs4.element.ResultSet# 不能用name.string,原因是这里的name标签内有两个字符串子项,所以返回None,详情参照help文档infoDict.update({'股票名称': name.text.split()[0]}) # 通过text以字符串形式获得name标签的所有字符串子项,然后用split()方法通过空格分隔字符串,提取股票名称# 获取其它的键值对信息keyList = stockInfo.find_all('dt') # 键在dt标签valueList = stockInfo.find_all('dd') # 值在dd标签for i in range(len(keyList)): key = keyList[i].text # 这里可以用keyList[i].string,获取键信息val = valueList[i].text # 获取值信息infoDict[key] = val # 往字典中添加键值对with open(fpath, 'a', encoding='utf-8') as f:# 以追加模式打开,因为有中文所以用utf-8编码f.write( str(infoDict) + '\n' ) # 这里为了输出美观,加了一个换行符count += 1print("\r当前股票信息下载进度:{:.2f}%".format(count*100/len(lst)),end="") # \r实现光标不换行,覆盖之前的答应内容,end=""实现禁掉print函数的自动换行功能except:count += 1print("\r当前股票信息下载进度:{:.2f}%".format(count*100/len(lst)),end="") # \r实现光标不换行,覆盖之前的答应内容,end=""实现禁掉print函数的自动换行功能traceback.print_exc() # 追踪错误,便于调试continuedef main():stock_list_url = "http://quote.eastmoney.com/stocklist.html"stock_info_url = "https://gupiao.baidu.com/stock/"output_file = "D://BaiduStockInfo.txt"slist = []getStockList(slist,stock_list_url)getStockInfo(slist,stock_info_url,output_file)main()

需要在cmd命令行下执行才能看到\r效果,在IDLE下\r的功能被禁止了。
执行过程如下:

六、代码的进一步优化

性能上:

  1. getStockList()函数中其实可以不用bs4库就可以匹配到股票信息,直接通过正则reg =re.compile( r’(sh\d{6}|sz\d{6})’)实现匹配。
  2. 在遍历keyList时,每次循环都会调用一次len(),浪费性能,完全可以只调用一次len()函数,然后赋值给一个变量,如:length
  3. 在打印进度条时len()函数的应用,每次执行print,会调用一次len(),处理同2。
    用户体验上:
  4. 我还想感受到我下载股票代码要花多久,多久后才是开始下载个股信息。
    改进后代码如下:
#!/usr/bin/env python
#-*- coding:utf-8 -*-import requests
from bs4 import BeautifulSoup
import re
import traceback # 追踪,便于调试def getHTMLText(url,code="utf-8"): # 获取网页内容try:r = requests.get(url)r.raise_for_status()r.encoding = codereturn r.textexcept:return ""def getStockList(lst,stockURL,fpath): # 获取股票列表html = getHTMLText(stockURL,"GB2312")pat = r'(sh\d{6}|sz\d{6})'reg = re.compile(pat)sl = reg.findall(html)length = len(sl)count = 0for i in sl:lst.append(i) # 这种方法不会改变原来传入的lst引用的地址with open(fpath,'a',encoding='utf-8') as f:f.write(str(i) +'\n')count +=1print('\r当前下载股票列表速度:{:.2f}%'.format(count*100/length),end='')def getStockInfo(lst,stockURL,fpath): # 获得每只个股的股票信息count = 0lstLength = len(lst)for stock in lst:url = stockURL + stock + ".html" # 构建爬取股票信息的URLhtml = getHTMLText(url) # 获取股票信息网页内容try:if html == "": # 有些网址打不开,或为空,则跳过continueinfoDict = {} # 以字典的形式保存股票信息,方便后面数据分析soup = BeautifulSoup(html,"html.parser")stockInfo = soup.find('div',attrs = {'class':'stock-bets'}) # 获取股票信息所在的标签,有可能部分网页丢失,所以要做类型判断if stockInfo: # stockInfo非None才执行name = stockInfo.find_all(attrs={'class':'bets-name'})[0] # 获取股票所在标签,这里注意find_all()返回的是一个bs4.element.ResultSet# 不能用name.string,原因是这里的name标签内有两个字符串子项,所以返回None,详情参照help文档infoDict.update({'股票名称': name.text.split()[0]}) # 通过text以字符串形式获得name标签的所有字符串子项,然后用split()方法通过空格分隔字符串,提取股票名称# 获取其它的键值对信息keyList = stockInfo.find_all('dt') # 键在dt标签valueList = stockInfo.find_all('dd') # 值在dd标签keyListLength = len(keyList)for i in range(keyListLength): key = keyList[i].text # 这里可以用keyList[i].string,获取键信息val = valueList[i].text # 获取值信息infoDict[key] = val # 往字典中添加键值对with open(fpath, 'a', encoding='utf-8') as f:# 以追加模式打开,因为有中文所以用utf-8编码f.write( str(infoDict) + '\n' ) # 这里为了输出美观,加了一个换行符count += 1print("\r当前股票信息下载进度:{:.2f}%".format(count*100/lstLength),end="") # \r实现光标不换行,覆盖之前的答应内容,end=""实现禁掉print函数的自动换行功能except:count += 1print("\r当前股票信息下载进度:{:.2f}%".format(count*100/lstLength),end="") # \r实现光标不换行,覆盖之前的答应内容,end=""实现禁掉print函数的自动换行功能traceback.print_exc() # 追踪错误,便于调试continuedef main():stock_list_url = "http://quote.eastmoney.com/stocklist.html"stock_info_url = "https://gupiao.baidu.com/stock/"output_file1 = "D://BaiduStockList.txt"output_file2 = "D://BaiduStockInfo.txt"slist = []getStockList(slist,stock_list_url,output_file1)print("\n") # 换行,避免两个进度条叠在一起getStockInfo(slist,stock_info_url,output_file2)main()

运行过程图:

输出结果:

七、心得体会

通过写这篇blog,很多语句都是一句一句在控制台下测试,理解每一步机器在做什么,虽然很耗时间,不过学到的东西比老师视频讲的要多,对于知识的理解也更深刻了。总结一下之前老师上课没有怎么提到的内容吧。

  1. Tag.text:返回以字符串的形式返回所有的子孙标签中的字符串。
  2. Tag.string:有且只有一个字符串时,可以跨越多层,通过递归方式返回一个字符串子项。如果没有字符串或者超过1个字符串子项都是返回None
  3. 充分利用控制台来测试代码,知道代码每一步在做什么,然后再写到脚本里面。
  4. 时刻关注性能和用户体验问题,写完代码记得优化。
  5. 基础记不清了,及时回去翻看课本和笔记,还有多利用help()查看官方文档。
  6. 再最后自己优化时,发生了一个bug,是python中函数传参数问题。

一般情况下,在python中函数的传参,很多人都在那儿争,到底是传的是它的值还是它的引用,其实最最最准确的说法,应该传的对象。那是什么意思呢,就是说,getStockList(lst,stockURL)函数第一个参数是list。那么这个类似的,假如说你是原地操作,比如说你list.append(),list.extend(),list.insert(),list.reverse(),list.sort()等,这些在原有的list的基础上进行操作的时候,他是改变原来那个list的内存地址的地方,但如果你写list等于另外一个新的list。这个时候list指到了新的内存地址。这样的话就导致了原来的内存地址的值没有变化,getStockInfo(lst,stockURL,fpath)调用时仍然为[]空列表。
重点看lst在getStockList(lst,stockURL)和getStockInfo(lst,stockURL,fpath)中参数传递的问题。
有兴趣的朋友可以看看试试下面这个代码,对比我最后优化的那个版本,有意思的是你会发现它很快就执行结束了,最后什么都没有输出。原因就在上面那段话。(作为初学者的我踩的又一个坑…)

#!/usr/bin/env python
#-*- coding:utf-8 -*-import requests
from bs4 import BeautifulSoup
import re
import traceback # 追踪,便于调试def getHTMLText(url,code="utf-8"): # 获取网页内容try:r = requests.get(url)r.raise_for_status()r.encoding = codereturn r.textexcept:return ""def getStockList(lst,stockURL): # 获取股票列表html = getHTMLText(stockURL,"GB2312")pat = r'(sh\d{6}|sz\d{6})'reg = re.compile(pat)lst = reg.findall(html)# 这个相当于把lst这个标签重新贴到了一个新的地址上,导致getStockInfo()函数调用lst时为空列表def getStockInfo(lst,stockURL,fpath): # 获得每只个股的股票信息count = 0lstLength = len(lst)for stock in lst:url = stockURL + stock + ".html" # 构建爬取股票信息的URLhtml = getHTMLText(url) # 获取股票信息网页内容try:if html == "": # 有些网址打不开,或为空,则跳过continueinfoDict = {} # 以字典的形式保存股票信息,方便后面数据分析soup = BeautifulSoup(html,"html.parser")stockInfo = soup.find('div',attrs = {'class':'stock-bets'}) # 获取股票信息所在的标签,有可能部分网页丢失,所以要做类型判断if stockInfo: # stockInfo非None才执行name = stockInfo.find_all(attrs={'class':'bets-name'})[0] # 获取股票所在标签,这里注意find_all()返回的是一个bs4.element.ResultSet# 不能用name.string,原因是这里的name标签内有两个字符串子项,所以返回None,详情参照help文档infoDict.update({'股票名称': name.text.split()[0]}) # 通过text以字符串形式获得name标签的所有字符串子项,然后用split()方法通过空格分隔字符串,提取股票名称# 获取其它的键值对信息keyList = stockInfo.find_all('dt') # 键在dt标签valueList = stockInfo.find_all('dd') # 值在dd标签keyListLength = len(keyList)for i in range(keyListLength): key = keyList[i].text # 这里可以用keyList[i].string,获取键信息val = valueList[i].text # 获取值信息infoDict[key] = val # 往字典中添加键值对with open(fpath, 'a', encoding='utf-8') as f:# 以追加模式打开,因为有中文所以用utf-8编码f.write( str(infoDict) + '\n' ) # 这里为了输出美观,加了一个换行符count += 1print("\r当前股票信息下载进度:{:.2f}%".format(count*100/lstLength),end="") # \r实现光标不换行,覆盖之前的答应内容,end=""实现禁掉print函数的自动换行功能except:count += 1print("\r当前股票信息下载进度:{:.2f}%".format(count*100/lstLength),end="") # \r实现光标不换行,覆盖之前的答应内容,end=""实现禁掉print函数的自动换行功能traceback.print_exc() # 追踪错误,便于调试continuedef main():stock_list_url = "http://quote.eastmoney.com/stocklist.html"stock_info_url = "https://gupiao.baidu.com/stock/"output_file = "D://BaiduStockInfo.txt"slist = []getStockList(slist,stock_list_url)getStockInfo(slist,stock_info_url,output_file)main()

八、参考资料

北京理工大学嵩天老师的《Python网络爬虫与信息提取》

基于Request+bs4-re技术路线实现股票数据定向爬虫相关推荐

  1. python如何爬虫股票数据_python爬虫实例,股票数据定向爬虫

    前言 我服了,这几天,怎么涨两天还不够跌一次,害.希望这个可以帮到自己! "股票数据定向爬虫"实例介绍 功能描述 目标:获取上交所和深交所所有股票的名称和交易信息 输出:保存到文件 ...

  2. 凤凰网股票数据定向爬虫——改编自北京理工大学嵩天老师的课程实例

    本文导航 前言 功能描述 技术路线 数据网站 程序结构设计 实现过程 实现结果 代码展示 可能遇到的问题 写在后面 前言 最近看到嵩天老师**<python网络爬虫与信息提取>的股票数据定 ...

  3. Python爬虫-股票数据定向爬虫(东方财富网)

    实例:股票数据定向爬虫 功能描述 目标:获取上交所和深交所所有股票的名称和交易信息 输出:保存到文件中 技术路线:requests­ bs4­ re 候选数据网站的选择 选取原则:股票信息静态存在于H ...

  4. Python网络爬虫实例1:股票数据定向爬虫

    Python网络爬虫实例:股票数据定向爬虫 一.功能描述 目标:获取上交所和深交所所有股票的名称和交易信息 输出:保存到文件中 技术路线:requests-bs4-re 二.候选数据网站选择 候选网站 ...

  5. Python 网络爬虫笔记8 -- 股票数据定向爬虫

    Python 网络爬虫笔记8 – 股票数据定向爬虫 Python 网络爬虫系列笔记是笔者在学习嵩天老师的<Python网络爬虫与信息提取>课程及笔者实践网络爬虫的笔记. 课程链接:Pyth ...

  6. 【Python爬虫学习】八、股票数据定向爬虫(2020年1月31日成功爬取中财网,百度股市通web版404了)

    功能描述: 目标:获取股票的名称和交易信息 输出:保存到文件中 程序结构设计: 步骤1:从中财网http://quote.cfi.cn/stockList.aspx获取股票列表 步骤2:根据股票列表获 ...

  7. python 东方财富网百度股票数据定向爬虫 实例

    功能: 1. 获取 上交所 深 交所的股票信息 2. 输出保存到文件中 技术路线: requests -beatiful soup - re 候选:数据网站选择 1.静态网站,信息静态存在HTML页面 ...

  8. 爬虫03_股票数据定向爬虫

    1.准备工作 功能描述: 目标:获取上交所和深交所所有股票的名称和交易信息 输出:保存到文件中 所用技术:requests.bs4.re.csv 数据网站选择: 新浪股票:http://finance ...

  9. 现在还有人说Python 爬虫没用吗?股票数据定向爬虫让你轻松了解股势

    说明 网站选择原则: 股票信息静态存在于html页面中,非js代码生成,没有Robbts协议限制. 选取方法: 打开网页,查看源代码,搜索网页的股票价格数据是否存在于源代码中. 需要相关python爬 ...

最新文章

  1. windows container (docker) 容器资料笔记
  2. iOS正则表达式验证
  3. [linux] 线程和wait命令,sleep命令
  4. python selenium 自动登录_windows7 python3.63使用selenium+webdriver 实现自动登录使用过程...
  5. 7-37 组个最小数 (20分)_波音737高度计上蹊跷的“8英尺”,09年土耳其航空1951号航班空难...
  6. 文本生成器(bzoj 1030)
  7. 海南橡胶机器人成本_「图说」海垦看点:海南橡胶联合北京理工华汇智能科技首创我国林间智能割胶机器人...
  8. C++函数概念解析(2)
  9. java大数模板_java大数模板
  10. jQuery的实现原理
  11. win7 64位_VS2010的fftw3配置
  12. Docker提高拉取官网镜像的速度
  13. matlab解决高等数学和线性代数的部分问题
  14. Rust LLDB 调试入门指北
  15. 【css】鼠标禁用样式
  16. 顶级黑客欢乐解析:宝宝事件中人肉搜索的七种方法
  17. linux12 -MYSQL数据库 --> 19数据库面试必备手册
  18. 01 Spark组件 —— Scala导言
  19. AutoHotKey的那些事儿:(一)、AutoHotkey常用命令
  20. 设计全局ER模型 数据库系统原理(2007版) 课程代码4735 笔记

热门文章

  1. 《人工智能》思维导图式课程总结
  2. C++类大小详尽讲解
  3. 计算机 创新方法举例,列举列举五种创新的方法并加以举例说明
  4. OLED电视再败给QLED,LG推广OLED不容易
  5. 基于Qt的代码加速(含Opencv)
  6. Linux下推荐的常用应用程序列表
  7. 8.Java-面向对象
  8. 使用jQuery.print.js打印
  9. 2021年毕业半年前端生涯总结
  10. WPF 计时器(支持倒计时、正计时)