Python網絡爬蟲實戰(三)照片定位與B站彈幕


之前兩篇已經說完了如何爬取網頁以及如何解析其中的數據,那么今天我們就可以開始第一次實戰了。

這篇實戰包含兩個內容。

* 利用爬蟲調用Api來解析照片的拍攝位置

* 利用爬蟲爬取Bilibili視頻中的彈幕

關於爬蟲調用Api這一說法,其實就是通過get或者post請求攜帶着參數,將內容發給對方服務器,服務器會根據請求的Api是哪個來進行處理。

比如說/delete?id=2和/save?id=1&name=antz這兩個請求就分別是刪除id等於2的數據,保存一條id等於1姓名為antz的數據。

此時我們就只需要向對方服務器發送出這個請求就可以了,requests.get(url)就這么簡單。

一.根據照片解析定位

不知道你平常拍照片有沒有在你手機的設置里仔細查看過,比如說下面這個選項【地理位置】。

6

打開它之后,我拍的照片上也沒有顯示地理位置啊?

這是因為這些數據被放在了照片文件數據里面,可能你很難理解,你可以回想一下之前我們說的get之后的響應,響應體分為響應頭和響應體。照片的數據也是一樣,有信息頭(隨便叫的)和數據體,信息頭里面有你這張照片的各種信息,拍攝時間地點設備等,而數據體就是你用看圖軟件打開時顯示在你眼中的那些了,我們平常關注到的只有數據體,只關心照片是不是好看,而信息頭的內容對我們來說其實無關緊要。

下面是我之前拍的一張照片經過解析獲得的信息頭數據,從里面可以看到照片尺寸,我的Make設備是HUAWEI,我的鏡頭數據,時間等等。

6

在Python中我們可以使用exifread庫來解析圖片的頭信息。

pip install exifread

調用exifread的process_file方法,參數傳入file,就可以得到照片的exif信息了。

img_exif = exifread.process_file(open("路徑", 'rb'))

返回的img_exif是一個字典數據,我們可以直接根據上面那張頭數據里面的標題來拿到對應的數據。

# 緯度數
latitude_gps = img_exif['GPS GPSLatitude'] 
# N,S 南北緯方向
latitude_direction = img_exif['GPS GPSLatitudeRef'] 
# 經度數
longitude_gps = img_exif['GPS GPSLongitude'] 
# E,W 東西經方向
longitude_direction = img_exif['GPS GPSLongitudeRef'] 

這樣我們就拿到南北緯以及經緯度了。

那么如何根據這些數據來獲得定位呢?

我們可以利用高德地圖開放的Api來將經緯度轉換為我們能夠直接讀懂的位置信息。

url = 'https://restapi.amap.com/v3/geocode/regeo?key={}&location={}'

上面是高德地圖逆向解析定位的api地址,key需要在高德地圖官網申請開發者之后拿到(很容易),location就是經緯度南北緯信息了。

resp = requests.get(url.format(api_key, location))
location_data = json.loads(resp.text)
address = location_data.get('regeocode').get('formatted_address')

上面的代碼是不是已經很簡單了,requests.get請求api拿到對方返回的結果,返回的數據的json數據,所以loads解析之后直接拿address即可。

這樣我們就可以拿到這張照片的拍攝地點了。

8

二.Bilibili彈幕爬蟲

先來思考一個問題,B站一個視頻的彈幕最多會有多少?

比較多的會有2000條吧,這么多數據,B站肯定是不會直接把彈幕和這個視頻綁在一起的。

也就是說,有一個視頻地址為https://www.bilibili.com/video/av67946325,你如果直接去requests.get這個地址,里面是不會有彈幕的,回想第一篇說到的攜程異步加載數據的方式,B站的彈幕也一定是先加載當前視頻的界面,然后再異步填充彈幕的。

接下來我們就可以打開火狐瀏覽器(平常可以火狐谷歌控制台都使用,因為谷歌里面因為插件被攔截下來的包在火狐可以抓到,同理谷歌也是)的控制台來觀察網絡請求了。

經過仔細排查之后,我找到了一個請求xml的,它后面跟了一個oid,查看它的響應內容之后可以發現它就是彈幕文件。

9

它的響應時間98毫秒,遠超其它幾個響應,所以說如果把彈幕直接放在視頻頁面,用戶體驗一定會很差。

9

找到彈幕了,爬取它很容易,但是我們想要是爬取固定av號視頻的彈幕,而不是說隨意去找一個oid來爬取彈幕,這樣我們都不知道爬下來的彈幕是哪個視頻的。

接下來我們就可以復制oid的117784982值,去視頻頁面搜索看看了,通過視頻來獲得它的oid再來爬xml彈幕就很方便了。

這次用了谷歌瀏覽器,在里面通過搜索oid果然搜索到相關的數據了。

9

其中cid是彈幕對應的id,aid對應視頻av號。

先把這個頁面爬取下來。

# encoding: utf-8

import requests

headers = {
    'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
    'Accept': 'text/html',
    'Cookie': "_uuid=1DBA4F96-2E63-8488-DC25-B8623EFF40E773841infoc; buvid3=FE0D3174-E871-4A3E-877C-A4ED86E20523155831infoc; LIVE_BUVID=AUTO8515670521735348; sid=l765gx48; DedeUserID=33717177; DedeUserID__ckMd5=be4de02fd64f0e56; SESSDATA=cf65a5e0%2C1569644183%2Cc4de7381; bili_jct=1e8cdbb5755b4ecd0346761a121650f5; CURRENT_FNVAL=16; stardustvideo=1; rpdid=|(umY))|ukl~0J'ulY~uJm)kJ; UM_distinctid=16ce0e51cf0abc-02da63c2df0b4b-5373e62-1fa400-16ce0e51cf18d8; stardustpgcv=0606; im_notify_type_33717177=0; finger=b3372c5f; CURRENT_QUALITY=112; bp_t_offset_33717177=300203628285382610"

}
resp = requests.get('https://www.bilibili.com/video/av67946325',headers=headers)
print(resp.text)

拿到了內容我們就要從中解析彈幕id了,對於這種規則紊亂的網頁,我們就不能用上一篇中Bs4解析了,而是使用正則表達式。

正則表達式最簡單的使用方式其實就是直接match。

re.search(匹配規則,文本).group()

12

觀察這里的內容,我們大致的匹配規則就有了。

cid={目標}&aid=av號

117784982就是我們的目標。

av_id = '67946325'

resp = requests.get('https://www.bilibili.com/video/av'+av_id,headers=headers)

match_rule = r'cid=(.*?)&aid'
oid = re.search(match_rule,resp.text).group().replace('cid=','').replace('&aid','')
print('oid='+oid)

先根據av號拿到視頻頁面,然后解析視頻頁面拿到oid,最后用oid去請求xml彈幕文件。

xml_url = 'https://api.bilibili.com/x/v1/dm/list.so?oid='+oid

resp = requests.get(xml_url,headers=headers)

print(resp)

這樣我們就完成B站彈幕爬蟲了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM