【Python爬虫学习实践】基于BeautifulSoup的网站解析及数据可视化
在上一次的學(xué)習(xí)實(shí)踐中,我們以Tencent職位信息網(wǎng)站為例,介紹了在爬蟲(chóng)中如何分析待解析的網(wǎng)站結(jié)構(gòu),同時(shí)也說(shuō)明了利用Xpath和lxml解析網(wǎng)站的一般化流程。在本節(jié)的實(shí)踐中,我們將以中國(guó)天氣網(wǎng)為例,并基于Beautiful Soup庫(kù)對(duì)其進(jìn)行數(shù)據(jù)解析,最后再簡(jiǎn)單說(shuō)明pyecharts數(shù)據(jù)可視化。
中國(guó)天氣網(wǎng)網(wǎng)址:http://www.weather.com.cn/textFC/hb.shtml
和之前的Tencent職位信息實(shí)踐一樣,我們先來(lái)分析一下我們所爬取的網(wǎng)站的結(jié)構(gòu)。在中國(guó)天氣網(wǎng)中,我們可以看到其是按照地區(qū)進(jìn)行了分類(lèi),如華北、東北、華東、華中等等,并且每一個(gè)地區(qū)都對(duì)應(yīng)著一個(gè)不同的頁(yè)面。
接下來(lái)我們?cè)賮?lái)看看我們需要獲取的數(shù)據(jù)信息。如下圖所示,每一個(gè)頁(yè)面的數(shù)據(jù)結(jié)構(gòu)都是以省市為塊的城市數(shù)據(jù)列表,而這些列表中的數(shù)據(jù)就是我們需要提取的信息。由于現(xiàn)在當(dāng)?shù)貢r(shí)間為夜晚,白天的信息也就沒(méi)有顯示了,因此在此以爬取夜間的天氣現(xiàn)象和最低氣溫為例,來(lái)說(shuō)明實(shí)踐中的Beautiful Soup數(shù)據(jù)提取的一般化流程。(Ps.注意這里顯示了一周的天氣情況,而后面的天氣信息都是完整的,后續(xù)會(huì)介紹如何爬取這些不同天的數(shù)據(jù))
通過(guò)上述簡(jiǎn)單分析,我們不難知道其實(shí)本次的數(shù)據(jù)獲取只需要得到相應(yīng)的URL地址,通過(guò)請(qǐng)求獲取其HTML源代碼,再利用解析庫(kù)解析出相應(yīng)的數(shù)據(jù)即可。下面我們就對(duì)此分過(guò)程介紹。
Step1——分析天氣URL
從之前的介紹我們知道中國(guó)天氣網(wǎng)劃分了幾個(gè)不同的地區(qū),每一個(gè)地區(qū)都對(duì)應(yīng)著一個(gè)URL,現(xiàn)在我們就先來(lái)看看這些URL的構(gòu)成法。
華北:http://www.weather.com.cn/textFC/hb.shtml
東北:http://www.weather.com.cn/textFC/db.shtml
華東:http://www.weather.com.cn/textFC/hd.shtml
華中:http://www.weather.com.cn/textFC/hz.shtml
…
經(jīng)過(guò)觀察分析,發(fā)現(xiàn)這幾個(gè)URL的域名都是一樣的,只是后面的path的文件名不同,因此我們可以大膽地推測(cè)其URL構(gòu)成法為:’http://www.weather.com.cn/textFC/+{}.shtml’,其中{}為地區(qū)名拼音縮寫(xiě)
接下來(lái),我們?cè)偻ㄟ^(guò)其他地區(qū)地URL來(lái)驗(yàn)證我們地推測(cè)。(十多秒過(guò)后…)嗯,結(jié)果發(fā)現(xiàn)和我們的推測(cè)是一樣的,如港澳臺(tái)就是引用’gat.shtml’。如此一來(lái),URL的獲取工作就好了。(其實(shí),天氣地區(qū)個(gè)數(shù)較少,網(wǎng)頁(yè)URL也比較少,我們也可以手動(dòng)獲取,不過(guò)這樣代碼就會(huì)顯得有些冗長(zhǎng))
## 遍歷獲取各地區(qū)天氣URL并傳入解析函數(shù) url = 'http://www.weather.com.cn/textFC/{}.shtml' for flag in ('hb', 'db', 'hd', 'hz', 'hn', 'xb', 'xn', 'gat'):parse_page_soup(url.format(flag))Step2——分析數(shù)據(jù)信息結(jié)構(gòu)
在獲取了天氣URL后,接下來(lái)就要分析我們所需提取的數(shù)據(jù)結(jié)構(gòu)是怎樣的。下面以華北地區(qū)為例,可以看到其省市天氣數(shù)據(jù)結(jié)構(gòu)如下。發(fā)現(xiàn)其數(shù)據(jù)都放在了一個(gè)class為conMidtab的div標(biāo)簽中,而這樣的標(biāo)簽共有7個(gè),那么又分別代表什么呢?細(xì)心觀察后發(fā)現(xiàn)只有1個(gè)的display 樣式為block,而其他的都是none。其實(shí)當(dāng)我們點(diǎn)擊其他日期的時(shí)候,我們會(huì)發(fā)現(xiàn)其他一個(gè)變成了block,而之前的那個(gè)變成了none,所以這些其實(shí)就是代表不同時(shí)間的天氣數(shù)據(jù),進(jìn)入節(jié)點(diǎn)查看具體信息后我們也發(fā)現(xiàn)這些節(jié)點(diǎn)的結(jié)構(gòu)都一樣,也再次說(shuō)明這就是用來(lái)控制顯示不同日期數(shù)據(jù)的。
每一個(gè)日期信息的獲取的原理都是一樣的,那么接下來(lái)我們就以北京(今天)為例,進(jìn)一步分析其數(shù)據(jù)組織結(jié)構(gòu)。瀏覽源碼我們可以發(fā)現(xiàn)在comMidtab的div標(biāo)簽下有5個(gè)comMidtab2的子div標(biāo)簽,這些其實(shí)就是代表華北地區(qū)的5個(gè)省市,每一個(gè)div為一個(gè)省市天氣的列表。
接下來(lái),在每一個(gè)子div中,我們可以找到一個(gè)table標(biāo)簽,而里面的tbody標(biāo)簽下又有若干個(gè)tr標(biāo)簽,掃描后可得知這些tr就是每一個(gè)省市數(shù)據(jù)列表中的行。
我們進(jìn)一步觀察每個(gè)tr標(biāo)簽的內(nèi)容,可以知道前兩個(gè)tr標(biāo)簽是列表的數(shù)據(jù)信息頭,而我們真正要獲取的數(shù)據(jù)為之后的tr標(biāo)簽。
這么一來(lái),我們便可以結(jié)合解析庫(kù)來(lái)獲取相應(yīng)的數(shù)據(jù)信息了。不過(guò)在解析的時(shí)候要注意一個(gè)問(wèn)題,那就是并不是所有的tr標(biāo)簽的子結(jié)構(gòu)都是一樣的。如下面的北京和海淀,北京比海淀多了第一個(gè)td,從圖中可以看出其實(shí)這是旁邊的省市名,因此在解析時(shí)需要設(shè)定一個(gè)好的解析策略。
##數(shù)據(jù)解析 import requests from bs4 import BeautifulSoupHEADERS = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36', }# 設(shè)置全局變量,用于保存提取的數(shù)據(jù) WEATHER_ALL = []# 解析數(shù)據(jù) def parse_page_soup(url):response = requests.get(url, headers=HEADERS)text = response.content.decode('utf-8')soup = BeautifulSoup(text, 'html5lib') #采用html5lib的解析器conMidtab = soup.find('div', attrs={'class': 'conMidtab'})tables = conMidtab.find_all('table')for table in tables:trs = table.find_all('tr')[2:] #舍棄前兩個(gè)信息頭數(shù)據(jù)for tr in trs:tds = tr.find_all('td')data = {'city': list(tds[-8].stripped_strings)[0], #為統(tǒng)一結(jié)構(gòu),倒序取值'weather': list(tds[-4].stripped_strings)[0],'min_temp': int(list(tds[-2].stripped_strings)[0])}WEATHER_ALL.append(data)這里需要說(shuō)明的是,為什么我們?cè)诮馕鰰r(shí)采用的時(shí)html5lib的解析器呢?其實(shí),采用lxml解析會(huì)快很多,但這不安全,因?yàn)樵诒敬蔚奶鞖饩W(wǎng)中,并不是所有的天氣頁(yè)面都是很規(guī)范的。我們可以先試一下用lxml來(lái)解析,看看會(huì)發(fā)生什么?如下圖,我們發(fā)現(xiàn)在解析港澳臺(tái)地區(qū)的時(shí)候發(fā)生了錯(cuò)誤,那么是為什么呢?
在錯(cuò)誤中提示列表越界,說(shuō)明沒(méi)有找到對(duì)應(yīng)的標(biāo)簽,是我們提取出問(wèn)題了?其實(shí)不然,之前在html5lib解析器下都是可以的,說(shuō)明問(wèn)題只出在了解析方式上,而這兩種解析器的區(qū)別重在容錯(cuò)性。查看源碼我們發(fā)現(xiàn),港澳臺(tái)地區(qū)的網(wǎng)頁(yè)并不是那么規(guī)范的,在數(shù)據(jù)表table標(biāo)簽中,其有前標(biāo)簽而缺少了尾標(biāo)簽</table>,也因此容錯(cuò)性不及html5lib的lxml解析就會(huì)出錯(cuò),所以我們?cè)趯?xiě)爬蟲(chóng)時(shí)要先確定好解析器種類(lèi),也可使用動(dòng)態(tài)解析器。
Step3——數(shù)據(jù)可視化
在爬取獲得數(shù)據(jù)后,接下來(lái)我們簡(jiǎn)單地按照最低氣溫排序并對(duì)前12個(gè)城市的數(shù)據(jù)進(jìn)行可視化處理。
對(duì)于排序,因?yàn)槲覀兇鎯?chǔ)體的是列表對(duì)象,可以使用內(nèi)置的sort()方法,而我們存儲(chǔ)的元素類(lèi)型為字典結(jié)構(gòu)并對(duì)某一屬性值(最低氣溫)排序,因此調(diào)用方法時(shí)我們需要傳入一個(gè)排序關(guān)鍵字參數(shù)key,并通過(guò)lambda表達(dá)式使其與字典中的屬性相關(guān)聯(lián)(這里也恰好解釋了之前獲取最低氣溫時(shí)為什么要存儲(chǔ)為int類(lèi)型)。
于可視化處理,我們可以借助一個(gè)名為pyecharts的工具庫(kù),使用它可以很方便地繪制各類(lèi)地?cái)?shù)據(jù)圖。安裝方法也很簡(jiǎn)單,使用pip安裝即可(pip install pyecharts),具體的使用方法在此不在敘述,大家可以參看中文文檔http://pyecharts.org/#/
## 對(duì)數(shù)據(jù)排序并按照最低氣溫取前12個(gè)城市制作可視化圖表 from pyecharts import BarWEATHER_ALL.sort(key=lambda data: data['min_temp']) data = WEATHER_ALL[0:12]cities = list(map(lambda x: x['city'], data)) #橫軸數(shù)據(jù)列表 temps = list(map(lambda x: x['min_temp'], data)) #縱軸數(shù)據(jù)列表 chart = Bar("中國(guó)天氣最低氣溫排行榜") #實(shí)例化圖表并傳入標(biāo)題參數(shù) chart.add('',cities,temps) #添加一個(gè)圖表關(guān)系 chart.render('temperature.html') #繪制并存儲(chǔ)為html文件另外,在安裝pyecharts時(shí)顯示安裝成功,然而實(shí)際上使用時(shí)可能會(huì)出現(xiàn)如下的錯(cuò)誤,提示未找到pyecharts_snapshot模塊,具體解決措施可參看中文文檔(見(jiàn)下圖)
?
至此,上述便是基于Beautiful Soup庫(kù)解析網(wǎng)站的一個(gè)實(shí)踐,同時(shí)也簡(jiǎn)單地介紹了數(shù)據(jù)可視化的內(nèi)容。其實(shí)無(wú)論Beautiful Soup還是之前的lxml,解析的一般流程都大致相同,只是適用的環(huán)境和解析速度有所區(qū)別,在實(shí)際的爬取工作中還需要認(rèn)真分析網(wǎng)頁(yè)結(jié)構(gòu),采取合適的爬取機(jī)制和手段。
轉(zhuǎn)載于:https://www.cnblogs.com/Unikfox/p/9688807.html
總結(jié)
以上是生活随笔為你收集整理的【Python爬虫学习实践】基于BeautifulSoup的网站解析及数据可视化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 中国农业银行怎么取消短信服务费(《中国》
- 下一篇: 数据之路 Day5 - Python基础