最近由于工作需要到踏,需要一個(gè)關(guān)于現(xiàn)在所有手機(jī)型號(hào)的信息表碑韵∪郑看了很多電商網(wǎng)站都會(huì)有手機(jī)種類和對(duì)其的詳細(xì)介紹,但檢查元素發(fā)現(xiàn)獲取這些信息遠(yuǎn)比想象中要難森缠,現(xiàn)在很多網(wǎng)站做的反爬措施還是很到位的拔鹰。在開發(fā)者工具中根本找不到一個(gè)合適的response對(duì)象。于是聯(lián)想贵涵,是否能從app端突破這個(gè)限制呢列肢,突然想起來在app端可以用抓包工具進(jìn)行抓取request和response等其他所有信息。于是啟發(fā)是否可以通過這點(diǎn)來越過爬蟲瓶頸呢宾茂?
前期準(zhǔn)備
研究了研究這個(gè)app抓包工具瓷马,感覺還是很好用的。所謂“工欲善其事必先利其器”跨晴,反正能達(dá)到所要求目的就好欧聘,感覺這個(gè)工具還是不錯(cuò)的,先推薦給大家坟奥。https://www.charlesproxy.com/
開始
在爬取時(shí)树瞭,我選了愛回收這個(gè)app進(jìn)行了實(shí)驗(yàn),感覺其實(shí)這個(gè)app的信息還是蠻全的爱谁,翻了翻他的手機(jī)回收的信息全是我想要的信息。
至于有關(guān)Charles怎么使用孝偎,請(qǐng)大家查閱其他資料访敌。此處不做多的介紹。
觀察
在對(duì)app的手機(jī)列表進(jìn)行查閱時(shí)衣盾,可以看到在charles中抓來的包
仔細(xì)觀察可以看到請(qǐng)求的url寺旺、請(qǐng)求方法、請(qǐng)求頭势决、請(qǐng)求體阻塑、響應(yīng)頭、響應(yīng)體等果复。
其實(shí)一開始的想法還是正統(tǒng)的爬蟲想法陈莽,仿照app的請(qǐng)求的方式進(jìn)行發(fā)送請(qǐng)求欺騙服務(wù)器來獲取數(shù)據(jù),但在postman中進(jìn)行測(cè)試的時(shí)候傳入這些值確實(shí)能夠獲取到剛才已經(jīng)發(fā)送過請(qǐng)求的數(shù)據(jù)json包,但是對(duì)于未發(fā)送過的請(qǐng)求的數(shù)據(jù)來說返回的卻是一個(gè)null走搁。
不難發(fā)現(xiàn)其實(shí)在發(fā)送請(qǐng)求時(shí)独柑,在請(qǐng)求的url中參數(shù)中有sig、timestamp和token私植,這三個(gè)參數(shù)除了時(shí)間戳剩余兩個(gè)都是加密過的忌栅,如果我仿照爬蟲的話我需要帶上這幾個(gè)參數(shù),對(duì)于token來說這幾次請(qǐng)求token都是一樣的曲稼,可以暫時(shí)寫一個(gè)固定的放進(jìn)去索绪,時(shí)間戳也可用time模塊來獲取,但是sig這個(gè)參數(shù)不知道是有什么參數(shù)構(gòu)成并且加密的贫悄,這就讓整個(gè)過程變得很棘手者春。在仿照瀏覽器發(fā)送請(qǐng)求時(shí)我需要知道這個(gè)sig參數(shù)是有什么構(gòu)成并且加密的,看似是個(gè)md5加密清女,但md5加密也不可逆钱烟,那就只能暫時(shí)放下這條路。
但是經(jīng)過研究這個(gè)charles工具發(fā)現(xiàn)每次其實(shí)都是帶著response的嫡丙,我就直接人工存下來就好了然后通過腳本處理一下這些文件就拿到了想要的數(shù)據(jù)拴袭。
文件批量處理
批量存儲(chǔ)這些文件到本地,其實(shí)感覺這個(gè)數(shù)據(jù)還是對(duì)自己的很友好的曙博,每個(gè)文件中都是標(biāo)準(zhǔn)的json格式拥刻,但唯一不好之處就是突然發(fā)現(xiàn)這些文件都沒有后綴名稱,總共保存的文件就有好幾百個(gè)父泳,于是我寫了一個(gè)shell腳本rename.sh來批量給這些文件加上后綴名“.json”
for i in ~/Desktop/product/*;
do mv "$i" "${i%}.json";
done
數(shù)據(jù)處理
這樣有了json文件的話就比較好獲取到我想要的信息了般哼,將json轉(zhuǎn)成字典,分析結(jié)構(gòu)就可以去除我想要的信息進(jìn)行相應(yīng)操作了惠窄。
首先獲取指定目錄的所有json文件蒸眠,先將路徑加入到列表中。
# 獲取當(dāng)前指定路徑下的所有json文件
def parse_dir(root_dir):
"""
:param root_dir:
:return:
"""
path = Path(root_dir)
all_json_file = list(path.glob('*.json'))
parse_result = []
for json_file in all_json_file:
parse_result.append(str(json_file))
return parse_result
通過json路徑讀取json杆融,并將其轉(zhuǎn)換成字典以便后續(xù)操作。
# 讀取json
def load_json(file):
"""
:param file:
:return:
"""
file = open(file, encoding='utf-8') # 設(shè)置以u(píng)tf-8解碼模式讀取文件脾歇,encoding參數(shù)必須設(shè)置蒋腮,否則默認(rèn)以gbk模式讀取文件,當(dāng)文件中包含中文時(shí)藕各,會(huì)報(bào)錯(cuò)
file_data = json.load(file)
data_list = file_data['data']
phone_list = []
for item in data_list:
phone_name = item['name']
phone_img = item['imgUrl']
top_price = item['topPrice']
brand_id = item['brandId']
phone_name = format_name(phone_name) # 格式化手機(jī)名稱為正確格式
img_download(phone_name, phone_img) # 根據(jù)json中的圖片url下載圖片到指定位置
phone_dict = {
"phone_name": phone_name,
"phone_img": phone_img,
"top_price": top_price,
"brand_id": brand_id,
"img_path": os.getcwd() + '/image/' + phone_name + '.png'
}
phone_list.append(phone_dict)
return phone_list
轉(zhuǎn)換成字典后直接寫入到EXCEL表格中就好了池摧。
# 生成excel文件
def generate_excel(row, col, expenses):
"""
:param row:
:param col:
:param expenses:
:return:
"""
workbook = xlsxwriter.Workbook('./tran_data.xlsx')
worksheet = workbook.add_worksheet()
bold_format = workbook.add_format({'bold': True}) # 設(shè)定格式,字典中格式為指定選項(xiàng)
money_format = workbook.add_format({'num_format': '$#,##0'}) # bold:加粗激况,num_format:數(shù)字格式
date_format = workbook.add_format({'num_format': 'mmmm d yyyy'})
worksheet.set_column(1, 1, 15) # 將二行二列設(shè)置寬度為15(從0開始)
worksheet.write('A1', '手機(jī)名稱', bold_format) # 用符號(hào)標(biāo)記位置作彤,例如:A列1行
worksheet.write('B1', '手機(jī)圖片', bold_format)
worksheet.write('C1', '最高價(jià)', bold_format)
worksheet.write('D1', '品牌ID', bold_format)
worksheet.write('E1', '本地圖片地址', bold_format)
for item in expenses: # 使用write_string方法膘魄,指定數(shù)據(jù)格式寫入數(shù)據(jù)
worksheet.write_string(row, col, str(item['phone_name']))
worksheet.write_string(row, col + 1, item['phone_img'])
worksheet.write_string(row, col + 2, str(item['top_price']))
worksheet.write_string(row, col + 3, str(item['brand_id']))
worksheet.write_string(row, col + 4, item['img_path'])
row += 1
workbook.close()
return row
最后附上項(xiàng)目源碼地址https://github.com/PeterPZhang/Simple_json_download_transformxlsx