目錄
- 一、mysql數(shù)據(jù)庫(kù)建表
- 二、下面直接上代碼(爬蟲(chóng)方法)
- 三、插入數(shù)據(jù)庫(kù)
- 四、總結(jié)一下爬取數(shù)據(jù)的步驟:
思路:使用Python爬蟲(chóng)對(duì)騰訊疫情網(wǎng)站世界疫情數(shù)據(jù)進(jìn)行爬取,封裝成一個(gè)函數(shù)返回一個(gè)
字典數(shù)據(jù)格式的對(duì)象,寫(xiě)另一個(gè)方法調(diào)用該函數(shù)接收返回值,和數(shù)據(jù)庫(kù)取得連接后把
數(shù)據(jù)存儲(chǔ)到mysql數(shù)據(jù)庫(kù)。
一、mysql數(shù)據(jù)庫(kù)建表
CREATE TABLE world(
id INT(11) NOT NULL AUTO_INCREMENT,
dt DATETIME NOT NULL COMMENT '日期',
c_name VARCHAR(35) DEFAULT NULL COMMENT '國(guó)家',
continent VARCHAR(35) DEFAULT NULL COMMENT '所屬大洲',
nowConfirm INT(11) DEFAULT NULL COMMENT '累計(jì)確診',
confirm INT(11) DEFAULT NULL COMMENT '當(dāng)日現(xiàn)存確診',
confirmAdd INT(11) DEFAULT NULL COMMENT '當(dāng)日新增確診',
suspect INT(11) DEFAULT NULL COMMENT '剩余疑似',
heal INT(11) DEFAULT NULL COMMENT '累計(jì)治愈',
dead INT(11) DEFAULT NULL COMMENT '累計(jì)死亡',
confirmAddCut INT(11) DEFAULT NULL COMMENT 'confirmAddCut',
confirmCompare INT(11) DEFAULT NULL COMMENT 'confirmCompare',
nowConfirmCompare INT(11) DEFAULT NULL COMMENT 'nowConfirmCompare',
healCompare INT(11) DEFAULT NULL COMMENT 'healCompare',
deadCompare INT(11) DEFAULT NULL COMMENT 'deadCompare',
PRIMARY KEY(id)
)ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
注意建立的表,數(shù)據(jù)的名字,數(shù)據(jù)的長(zhǎng)度,數(shù)據(jù)的類型,主鍵的定義一定要小心仔細(xì)。
這里博主出現(xiàn)了幾個(gè)小錯(cuò)誤:
①數(shù)據(jù)表的主鍵不可以設(shè)置為日期,因?yàn)樵谥笈廊?shù)據(jù)之后可以看到,網(wǎng)站給的數(shù)據(jù)是同一天的,
因?yàn)橹麈I不可以有重復(fù),所以相同的日期是不可以作為主鍵定義的。
②設(shè)置int類型的id作為數(shù)據(jù)表的主鍵,那么存在一個(gè)問(wèn)題,在往表里插入數(shù)據(jù)的時(shí)候,id位置的數(shù)據(jù)值需要考慮,
這個(gè)方法可以解決:可以在傳值的時(shí)候把id的值設(shè)定為 0,前提是id是自增的,
這樣數(shù)據(jù)庫(kù)是可以自己處理id的,依然是從0開(kāi)始自增,這樣避免了不給id傳值導(dǎo)致Null的異常。
③博主使用的mysql可視化工具默認(rèn)在一個(gè)頁(yè)面顯示30條記錄,在右上角可以改變顯示的記錄數(shù),因?yàn)楸敬尾迦氲?/p>
是185條數(shù)據(jù),所以在插入完之后如果發(fā)現(xiàn)數(shù)據(jù)不對(duì),可以看看可視化工具是不是有什么設(shè)置導(dǎo)致的。
二、下面直接上代碼(爬蟲(chóng)方法)
"""
獲取全球疫情數(shù)據(jù)
"""
def get_world_data():
url='https://api.inews.qq.com/newsqa/v1/automation/foreign/country/ranklist'
headers={'user-agent': 'WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'}
# 創(chuàng)建會(huì)話對(duì)象
# session = requests.session()
# 請(qǐng)求接口
# result = session.get('https://api.inews.qq.com/newsqa/v1/automation/foreign/country/ranklist')
# 打印結(jié)果
# print(result.text)
res = requests.get(url, headers=headers)
# print(res.text)
response_data_0 = json.loads(res.text.replace('jQuery34102848205531413024_1584924641755(', '')[:-1]) #轉(zhuǎn)化json對(duì)象
# print(response_data_0.keys())
# print(response_data_0)
response_data_1=response_data_0['data']
# print(response_data_1)
# print(response_data_1[0].keys())
# data = jsonpath.jsonpath(resJson_1, '$.data.*')
# print(resJson_1.keys())
# for d in data:
# res = '日期:' + d['date'] + '--' + d['continent'] + '--' + d['name'] + '--' + '新增確診:' + str(
# d['confirmAdd']) + '累計(jì)確診:' + str(d['confirm']) + '治愈:' + str(d['heal']) + '死亡:' + str(d['dead'])
# file = r'C:/Users/Administrator/Desktop/world_data.txt'
# with open(file, 'w+', encoding='utf-8') as f:
# f.write(res + '\n') # 加\n換行顯示
# f.close()
world={}
for i in response_data_1:
temp=i['y']+'.'+i['date']
tup = time.strptime(temp, '%Y.%m.%d')
dt = time.strftime('%Y-%m-%d', tup) # 改變時(shí)間格式,插入數(shù)據(jù)庫(kù) 日期
# print(ds)
c_name=i['name'] #國(guó)家
continent=i['continent'] #所屬大洲
nowConfirm=i['nowConfirm'] #現(xiàn)有確診
confirm=i['confirm'] #累計(jì)確診
confirmAdd=i['confirmAdd'] #新增確診
suspect=i['suspect'] #現(xiàn)有疑似
heal=i['heal'] #累計(jì)治愈
dead=i['dead'] #累計(jì)死亡
confirmAddCut=i['confirmAddCut']
confirmCompare=i['confirmCompare']
nowConfirmCompare=i['nowConfirmCompare']
healCompare=i['healCompare']
deadCompare=i['deadCompare']
world[c_name] = {'dt':dt ,
'continent': continent,
'nowConfirm': nowConfirm,
'confirm': confirm,
'confirmAdd': confirmAdd,
'suspect': suspect,
'heal': heal,
'dead': dead,
'confirmAddCut': confirmAddCut,
'confirmCompare': confirmCompare,
'nowConfirmCompare': nowConfirmCompare,
'healCompare': healCompare,
'deadCompare': deadCompare,
}
return world
三、插入數(shù)據(jù)庫(kù)
def insert_world():
"""
更新 world 表
:return:
"""
cursor = None
conn = None
try:
dic = get_world_data()
print(dic)
conn, cursor = get_conn()
sql = "insert into world values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
sql_query = 'select %s=(select dt from world order by id desc limit 1)' #對(duì)比當(dāng)前最大時(shí)間戳
cursor.execute(sql_query,dic['美國(guó)']['dt'])
if not cursor.fetchone()[0]:
print(f"{time.asctime()}開(kāi)始插入世界數(shù)據(jù)")
for k, v in dic.items(): # item 格式 {'2021-01-13': {'confirm': 41, 'suspect': 0, 'heal': 0, 'dead': 1}
cursor.execute(sql, [0,v.get('dt'), k, v.get("continent"), v.get("nowConfirm"),
v.get("confirm"), v.get("confirmAdd"),v.get("suspect"),v.get("heal"), v.get("dead")
, v.get("confirmAddCut"), v.get("confirmCompare"), v.get("nowConfirmCompare"), v.get("healCompare"),
v.get("deadCompare")])
conn.commit() # 提交事務(wù)
print(f"{time.asctime()}插入世界數(shù)據(jù)完畢")
else:
print(f"{time.asctime()}世界數(shù)據(jù)已是最新數(shù)據(jù)!")
except:
traceback.print_exc()
finally:
close_conn(conn, cursor)
總結(jié)一下在完成這兩個(gè)方法的過(guò)程中遇到的問(wèn)題,首先是最基礎(chǔ)的問(wèn)題,數(shù)據(jù)的類型和格式的轉(zhuǎn)換,這里主要是指json字符串和
Python里對(duì)應(yīng)的數(shù)據(jù)對(duì)象(list和字典)。
(1)一般來(lái)講對(duì)我們而言,需要抓取的是某個(gè)網(wǎng)站或者某個(gè)應(yīng)用的內(nèi)容,提取有用的價(jià)值。內(nèi)容一般分為三部分,
結(jié)構(gòu)化的數(shù)據(jù)、半結(jié)構(gòu)化的數(shù)據(jù)和非機(jī)構(gòu)化數(shù)據(jù)。
1.結(jié)構(gòu)化數(shù)據(jù):
可以用統(tǒng)一的結(jié)構(gòu)加以表示的數(shù)據(jù)??梢允褂藐P(guān)系型數(shù)據(jù)庫(kù)表示和存儲(chǔ),表現(xiàn)為二維形式的數(shù)據(jù),一般特點(diǎn)是:數(shù)據(jù)以行為單位,
一行數(shù)據(jù)表示一個(gè)實(shí)體的信息,每一行的數(shù)據(jù)的屬性是相同的。
2.半結(jié)構(gòu)化數(shù)據(jù):
結(jié)構(gòu)化數(shù)據(jù)的一種形式,并不符合關(guān)系型數(shù)據(jù)庫(kù)或其他數(shù)據(jù)表的形式關(guān)聯(lián)起來(lái)的數(shù)據(jù)模型結(jié)構(gòu),但包含相關(guān)標(biāo)記,
用來(lái)分隔語(yǔ)義元素以及對(duì)記錄和字段進(jìn)行分層。因此他也被成為自描述的結(jié)構(gòu)。常見(jiàn)的半結(jié)構(gòu)數(shù)據(jù)有:html,xml和json等、
實(shí)際上是以樹(shù)或者圖的結(jié)構(gòu)來(lái)存儲(chǔ)的。
對(duì)于半結(jié)構(gòu)化數(shù)據(jù),節(jié)點(diǎn)中屬性的順序是不重要的,不同的半結(jié)構(gòu)化數(shù)據(jù)的屬性的個(gè)數(shù)是不一樣的。這樣的數(shù)據(jù)格式,
可以自由的表達(dá)很多有用的信息,
包含自描述信息。所以半結(jié)構(gòu)化數(shù)據(jù)的擴(kuò)展性很好,特別適合于在互聯(lián)網(wǎng)中大規(guī)模傳播。
3.非結(jié)構(gòu)化數(shù)據(jù)
就是沒(méi)有固定的結(jié)構(gòu)。各種文檔,圖片,視頻或者音頻都屬于非結(jié)構(gòu)化數(shù)據(jù)。對(duì)于這類數(shù)據(jù),我們一般直接整體進(jìn)行存儲(chǔ),而且一般存儲(chǔ)為二進(jìn)制形式。
原文鏈接:www.jb51.net/article/208448.htm
json數(shù)據(jù)
json(JavaScript Object Notation,JS對(duì)象標(biāo)記)是一種輕量級(jí)的數(shù)據(jù)交換格式。
基于ECMAScript(w3c制定的JS規(guī)范)的一個(gè)子集,采用完全獨(dú)立于編程語(yǔ)言的文本格式來(lái)存儲(chǔ)和表示數(shù)據(jù)。
簡(jiǎn)潔和清晰的層次結(jié)構(gòu)使得JSON成為理想的數(shù)據(jù)交換語(yǔ)言。
特點(diǎn):易于閱讀、易于機(jī)器生成、有效提升網(wǎng)絡(luò)速度。
JSON語(yǔ)法規(guī)則:
在JS語(yǔ)言中,一切都是對(duì)象。因此,任何支持的類型都可以通過(guò)json來(lái)表示。
例如字符串、數(shù)字,對(duì)象,數(shù)組。
Js中對(duì)象和數(shù)組是比較特殊并且常用的兩種類型:
1、對(duì)象表示為鍵值對(duì){name:'zhangsan',age:'7'}
2、數(shù)據(jù)有逗號(hào)分隔[1,2,3,4,5]
3、花括號(hào)保存對(duì)象
4、方括號(hào)保存數(shù)組。
js的對(duì)象就相當(dāng)于python中的字典
js的數(shù)組就相當(dāng)于Python中的列表
因?yàn)閖son用來(lái)存儲(chǔ)js的對(duì)象或者數(shù)組,所以在Python中我們可以將json轉(zhuǎn)化為list或者dict。
解析json的包json:
json.dumps(python的list或者dict)---->(返回值)---->json字符串。
json.loads(json字符串)------>(返回值)----->python的list或者dict.
json.dump(list/dict,fp)—>list,或者字典保存到j(luò)son文件中。
json.load(fp)—>list/dict:從json文件中讀出json數(shù)據(jù)。
json鍵值對(duì)是用來(lái)保存js對(duì)象的一種方式,和js對(duì)象的寫(xiě)法頁(yè)大同小異,比如:
{“firstName”:“Json”,“Class”:“aid1111”}等價(jià)于下面這條js語(yǔ)句:{firstName:“Json”,Class:“aid1111”}。
很多人搞不清楚json和js對(duì)象的關(guān)系,甚至誰(shuí)是誰(shuí)都不清楚。其實(shí)可以這么理解:
【JSON是JS對(duì)象的字符串表達(dá)式,他使用文本形式表示一個(gè)JS對(duì)象的信息,本質(zhì)是一個(gè)字符串?!?br />
如var obj = {a:“hello”,b:“World”}這是一個(gè)js對(duì)象。注意,鍵名也是可以用引號(hào)包裹的var json = ' {“a”:“hello”,“b”:“World”}'這是一個(gè)json字符串,本質(zhì)上是一個(gè)字符串。
JSON作為數(shù)據(jù)包格式傳輸?shù)臅r(shí)候具有更高的效率,這是因?yàn)镴SON不想xml那樣具有嚴(yán)格的閉合標(biāo)簽,這就讓有效數(shù)據(jù)量與總數(shù)據(jù)包比大大提升,從而減少同等數(shù)據(jù)流量的情況下,網(wǎng)絡(luò)的傳輸?shù)膲毫Υ蟠鬁p低。
之前寫(xiě)過(guò)一篇關(guān)于爬取中國(guó)疫情數(shù)據(jù)的博客文章,那里爬取的每日疫情數(shù)據(jù)和全球爬取的疫情數(shù)據(jù)格式有一點(diǎn)點(diǎn)不同:
這是中國(guó)的疫情數(shù)據(jù),注意箭頭指的地方,這里的data對(duì)應(yīng)的key是字典
這是全球疫情,注意這里data對(duì)應(yīng)的是list
數(shù)據(jù)的格式非常重要,因?yàn)樵诤罄m(xù)需要把網(wǎng)頁(yè)爬取的數(shù)據(jù)接受之后,還要把數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫(kù),所以中間數(shù)據(jù)的格式必須清楚,
比如list類型的可以通過(guò)下標(biāo)去訪問(wèn),而字典只可以通過(guò)name來(lái)訪問(wèn),字典是不提供索引的,所以不可以通過(guò)下標(biāo)訪問(wèn)。還
有就是數(shù)據(jù)庫(kù)里的日期格式一定要注意轉(zhuǎn)換再插入。
四、總結(jié)一下爬取數(shù)據(jù)的步驟:
(1)首先需要導(dǎo)入需要的包:
import requests
import pymysql
import time
import json
import traceback
(2)通過(guò)request向被爬取網(wǎng)站的url發(fā)起一個(gè)請(qǐng)求(如果網(wǎng)站有反爬取手段,需要在請(qǐng)求里加上headers)
獲取headers:
到指定網(wǎng)站,瀏覽器按F12,之后在網(wǎng)絡(luò)那一個(gè)選項(xiàng)里可以看到。
(3)獲取和解析數(shù)據(jù)
url='https://api.inews.qq.com/newsqa/v1/automation/foreign/country/ranklist'
headers={'user-agent': 'WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'}
res = requests.get(url, headers=headers)
# print(res.text)
response_data_0 = json.loads(res.text.replace('jQuery34102848205531413024_1584924641755(', '')[:-1]) #轉(zhuǎn)化json對(duì)象
這里進(jìn)行了第一步解析,通過(guò)json.loads( ) 方法把從網(wǎng)頁(yè)獲取的json字符串?dāng)?shù)據(jù)轉(zhuǎn)化成Python對(duì)應(yīng)的list或者字典。
如果第一步解析之后data對(duì)應(yīng)的value不是list,那么可以進(jìn)行第二次解析,本次操作中,世界疫情數(shù)據(jù)的data對(duì)
應(yīng)的數(shù)據(jù)是一個(gè)list,所以也就不需要進(jìn)行第二次轉(zhuǎn)化,可以直接通過(guò)list的下標(biāo)去訪問(wèn)。
數(shù)據(jù)轉(zhuǎn)化是必要的,在網(wǎng)絡(luò)中json字符串傳遞小巧安全速度快,但是我們讀取數(shù)據(jù),如果直接對(duì)字符串進(jìn)行操作
會(huì)非常不方便,所以我們需要解析json字符串,也就是通過(guò)json.loads()方法把字符串轉(zhuǎn)化成Python對(duì)應(yīng)的list或
者字典對(duì)象,這樣我們?cè)L問(wèn)操作這些數(shù)據(jù)會(huì)變得簡(jiǎn)單。
以上就是Python爬蟲(chóng)爬取全球疫情數(shù)據(jù)并存儲(chǔ)到mysql數(shù)據(jù)庫(kù)的步驟的詳細(xì)內(nèi)容,更多關(guān)于python 爬取疫情數(shù)據(jù)存儲(chǔ)到mysql的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
您可能感興趣的文章:- 教你如何使用Python快速爬取需要的數(shù)據(jù)
- python爬取豆瓣電影TOP250數(shù)據(jù)
- python爬取鏈家二手房的數(shù)據(jù)
- Python手拉手教你爬取貝殼房源數(shù)據(jù)的實(shí)戰(zhàn)教程
- Python數(shù)據(jù)分析之Python和Selenium爬取BOSS直聘崗位
- python爬蟲(chóng)之爬取谷歌趨勢(shì)數(shù)據(jù)
- python selenium實(shí)現(xiàn)智聯(lián)招聘數(shù)據(jù)爬取
- python爬蟲(chóng)之教你如何爬取地理數(shù)據(jù)
- Python爬取騰訊疫情實(shí)時(shí)數(shù)據(jù)并存儲(chǔ)到mysql數(shù)據(jù)庫(kù)的示例代碼
- Python爬蟲(chóng)之自動(dòng)爬取某車之家各車銷售數(shù)據(jù)