寫(xiě)在前面的話
網(wǎng)上的教程都太簡(jiǎn)單了(代碼又太難了),我摸索了好一陣。所以這是一個(gè)特別啰嗦的教程怜珍,每一步都有截圖。
整個(gè)流程:
- 確保你的庫(kù)都全了
- 用賬號(hào)密碼登入網(wǎng)頁(yè)
- 取讀煉句信息
- 清洗數(shù)據(jù)
- 保存數(shù)據(jù)到Excel
- 附完整代碼
老規(guī)矩:安裝庫(kù)
import requests
import json
import re
import xlwt
確認(rèn)一下凤粗,你有沒(méi)有requests
和xlwt
的庫(kù)酥泛,沒(méi)有的話,裝一下
如果不裝嫌拣,代碼運(yùn)行不起來(lái)柔袁,你雙擊.py
文件,就直接閃退了
如果你在調(diào)試中運(yùn)行异逐,那會(huì)報(bào)錯(cuò)
賬號(hào)密碼登入
基本步驟:
(1)獲取網(wǎng)址捶索,得到【URL】
(2)輸入賬號(hào)密碼,得到【data】
(3)構(gòu)建Request Headers灰瞻,得到【headers】
(4)登入網(wǎng)頁(yè)
(1)URL
首先腥例,網(wǎng)頁(yè)類(lèi)型分為兩種辅甥,靜態(tài)和動(dòng)態(tài)的
靜態(tài)頁(yè)面 | 動(dòng)態(tài)頁(yè)面 |
---|---|
非結(jié)構(gòu)化數(shù)據(jù):HTML | 結(jié)構(gòu)化數(shù)據(jù):json,xml等 |
處理方式:正則表達(dá)式燎竖,xpath, beautifulsoup4 | 處理方式:直接轉(zhuǎn)化為python類(lèi)型 |
以扇貝網(wǎng)為例璃弄,瀏覽器為360極速瀏覽器
網(wǎng)址:
https://web.shanbay.com/web/account/login
扇貝網(wǎng)里面,部分網(wǎng)頁(yè)是靜態(tài)的构回,部分是動(dòng)態(tài)的
右擊“審查元素”夏块,或者F12,打開(kāi)開(kāi)發(fā)人員工具
點(diǎn)擊“Network”纤掸,把Preserve Log
勾選上拨扶,在左下角那個(gè)框里輸入“l(fā)ogin”(表示只看登入信息)
輸入賬號(hào)密碼,登入網(wǎng)頁(yè)
登入后茁肠,顯示如下
在這里可以看到,其實(shí)我們實(shí)際登入的網(wǎng)址是
https://apiv3.shanbay.com/bayuser/login
請(qǐng)求方式是POST
補(bǔ)充缩举,請(qǐng)求方式Request Method一般有兩種垦梆,GET和POST
- GET: 請(qǐng)求的URL會(huì)附帶查詢參數(shù)
- POST: 請(qǐng)求的URL不會(huì)附帶查詢參數(shù)
所以第一步,明確仅孩,我們是POST請(qǐng)求托猩,網(wǎng)址是https://apiv3.shanbay.com/bayuser/login
postUrl = 'https://apiv3.shanbay.com/bayuser/login'
(2)包含賬號(hào)密碼的data
剛剛那個(gè)界面,往下滑到最后
我們看到辽慕,請(qǐng)求是Request Payload
京腥,里面包含了我們賬號(hào)密碼的信息
還有一種方式是Form Data
,具體區(qū)別可參考
HTTP請(qǐng)求中的form data和request payload的區(qū)別
我們這里就講Request Payload
溅蛉,現(xiàn)在扇貝用這個(gè)
PayloadData = {
'account': "1********9",
'code_2fa': "",
'password': "Z*************6"
}
(3)headers
還是剛剛那個(gè)界面公浪,網(wǎng)上翻一點(diǎn),就能看到Request Header
船侧,我們選取其中部分信息欠气,構(gòu)造一個(gè)頭
我們選這3個(gè)數(shù)據(jù),自己假裝構(gòu)建一個(gè)Request Header
payloadHeader = {'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
'referer': "https://web.shanbay.com/web/account/login/",
'content-type': 'application/json'
}
(4)登入網(wǎng)頁(yè)
把剛剛得到的URL镜撩、Data预柒、headers整合起來(lái)
import requests # 獲取網(wǎng)頁(yè)的強(qiáng)大工具
import json # 動(dòng)態(tài)網(wǎng)頁(yè)要用
payloadHeader = {'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
'referer': "https://web.shanbay.com/web/account/login/",
'content-type': 'application/json'
}
postUrl = 'https://apiv3.shanbay.com/bayuser/login'
s = requests.Session() # 為了保存登入信息
PayloadData = {
'account': "1******9",
'code_2fa': "",
'password': "Z*******6"
}
r = s.post(postUrl, data=json.dumps(PayloadData), headers=payloadHeader)
# s.post,表示POST請(qǐng)求
這時(shí)候輸出r
的內(nèi)容袁梗,就能看到自己的昵稱(chēng)宜鸯、ID、用戶名等等遮怜,那就說(shuō)明淋袖,我們登入成功啦
這時(shí)候,我們已經(jīng)把登入的信息锯梁,保存在s
里面了
爬取煉句
如何獲取網(wǎng)頁(yè)接口
還是剛剛的開(kāi)發(fā)模式适贸,打開(kāi)我們想要爬取的網(wǎng)頁(yè)灸芳,然后看實(shí)際我們要獲取的網(wǎng)頁(yè)是什么?(我們獲取的網(wǎng)頁(yè)拜姿,和顯示的網(wǎng)頁(yè)烙样,不是同一個(gè))
比如扇貝上面顯示的是:
https://www.shanbay.com/sentence/book/all/常用/?id=10
但實(shí)際上是:
https://www.shanbay.com/api/v1/sentence/book/phrase/10/?_=1559715369583
這里發(fā)現(xiàn),獲取方式蕊肥,變成GET
了谒获。
剛剛我們講了POST
,現(xiàn)在就換成GET
我們輸網(wǎng)址的時(shí)候壁却,后面那個(gè)?_155.....
不需要輸入批狱,是一個(gè)時(shí)間戳
url = 'https://www.shanbay.com/api/v1/sentence/book/phrase/10'
GetUrl = s.get(url) # 這里換成get了,剛剛是s.post
TextWeb = GetUrl.text
print(TextWeb)
數(shù)據(jù)已經(jīng)都取讀了展东,只不過(guò)在系統(tǒng)儲(chǔ)存的時(shí)候赔硫,都是編碼\u02cc\
這種,轉(zhuǎn)成文字就好啦~
這里有個(gè)小技巧盐肃,可以一鍵轉(zhuǎn)換爪膊,后面會(huì)講
這爬出來(lái)的網(wǎng)頁(yè),密密麻麻砸王,眼花繚亂推盛,看不懂怎么辦?
這時(shí)候谦铃,你可以點(diǎn)Preview
耘成,這里面就好看很多
這和我們得到的數(shù)據(jù)是一致的,只是我們的數(shù)據(jù)需要轉(zhuǎn)換
清洗數(shù)據(jù):短語(yǔ)和單詞
短語(yǔ)和單詞相對(duì)簡(jiǎn)單一點(diǎn)驹闰,可以在網(wǎng)頁(yè)上直接讀取
(1)re.findall所有值
DataList = re.findall("{\"content.*?}",TextWeb)
我們通過(guò)re.findall得到的數(shù)據(jù)是有規(guī)律的瘪菌,每一個(gè)短語(yǔ),都相當(dāng)于一個(gè)字典
里面包含了content
和definition
兩部分的數(shù)據(jù)嘹朗,可以一鍵提取喲~
(2)把數(shù)據(jù)轉(zhuǎn)成字典
大家可以看到控嗜,實(shí)際上,這時(shí)候的類(lèi)型骡显,是一個(gè)str
字符串疆栏,我們要轉(zhuǎn)化成字典
,才方便操作
phrase_dict = json.loads(phrase) #用json.load就可以直接轉(zhuǎn)換
sheet.write(j, 0, phrase_dict['content']) #然后就可以直接提取字典內(nèi)容惫谤,保存到Excel
sheet.write(j, 1, phrase_dict['definition'])
這時(shí)候提取的數(shù)據(jù)壁顶,就很完美啦~
清洗數(shù)據(jù):煉句
煉句的獲取,比句子和短語(yǔ)稍微麻煩一點(diǎn)
因?yàn)樗畛醌@得的網(wǎng)頁(yè)溜歪,是一個(gè)匯總若专。比如有30課煉句,它就提供了30個(gè)鏈接蝴猪。
你需要先獲取鏈接调衰,然后再進(jìn)入各個(gè)網(wǎng)頁(yè)提取數(shù)據(jù)
for article in article_List:
article_dict = json.loads(article)
article_id = article_dict['article_id']
article_id_url = book_article_url+"/"+str(article_id)
Text_article_id = GetTextWeb(article_id_url,s)
content_article_1 = re.findall(" {\"zh-CN\": {\"content.*?}",Text_article_id)
for content1 in content_article_1:
content1 = content1[len("{\"zh-CN\":")+2:]
content_dict_1 = json.loads(content1)
sheet.write(m, 1, content_dict_1['content'])
m += 1
其實(shí)就是膊爪,來(lái)兩個(gè)for
循環(huán)。第一次確定具體鏈接嚎莉,第二次再提取數(shù)據(jù)米酬。
另外,扇貝里面包含簡(jiǎn)體和繁體解釋?zhuān)蠹铱梢宰孕羞x取趋箩。我現(xiàn)在是用的簡(jiǎn)體zh-CN
赃额。
取讀句子的時(shí)候,煉句還有個(gè)麻煩事叫确,它的網(wǎng)頁(yè)跳芳,竟然不是統(tǒng)一的。格式會(huì)有變化竹勉。但總體看下來(lái)飞盆,就是有2種結(jié)構(gòu)
content_article_2 = re.findall("(\"audio_name.*?), \"audio_urls",Text_article_id)
if content_article_2 == []:
content_article_2 = re.findall("(\"content\".*?\"),",Text_article_id)
for i in content_article_2:
if i[len("\"content\": \"")] == "\\":
content_article_2.remove(i)
for i in content_article_2:
if i[len("\"content\": \"")] == "\\":
content_article_2.remove(i)
所以用個(gè)if
判斷一下,第一種情況讀不出的時(shí)候次乓,就用第二種
完整代碼
# -*- coding: utf-8 -*-
"""
Created on Sat May 25 2019
@author: YangYang
"""
import requests
import json
import re
import xlwt
def Login(account,password):
payloadHeader = {'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
'referer': "https://web.shanbay.com/web/account/login/",
'content-type': 'application/json'
}
postUrl = 'https://apiv3.shanbay.com/bayuser/login'
s = requests.Session() # 為了保存登入信息
PayloadData = {
'account': account,
'code_2fa': "",
'password': password
}
r = s.post(postUrl, data=json.dumps(PayloadData), headers=payloadHeader)
return s,r
def GetTextWeb(url,s):
GetUrl = s.get(url)
return GetUrl.text
# 輸入賬號(hào)密碼登入
account =input("請(qǐng)輸入你的賬號(hào):")
password = input("請(qǐng)輸入你的密碼:")
s,r = Login(account,password)
print('\n')
print("賬號(hào)登入成功吓歇!")
# 打開(kāi)Excel
workbook = xlwt.Workbook() #定義workbook
# 輸入網(wǎng)址
sentence_number = 40 #這是煉句的編號(hào)
book_url = "https://www.shanbay.com/api/v1/sentence/userbook/" + str(sentence_number)
book_phrase_url = "https://www.shanbay.com/api/v1/sentence/book/phrase/"+ str(sentence_number)
book_article_url = "https://www.shanbay.com/api/v1/sentence/book/article/"+ str(sentence_number)
# 獲取煉句書(shū)的標(biāo)題
# 這里有個(gè)奇怪的點(diǎn),有些網(wǎng)頁(yè)能讀出來(lái)檬输,有些不能
# 所以最后,我還是手動(dòng)輸入了(我技術(shù)不行靶偌)
#Text_book = GetTextWeb(book_url,s)
#title = re.findall("(\"title\".*?),",Text_book)
#title = "{"+title[0]+"}" #轉(zhuǎn)成字典
#title_dict = json.loads(title)
#workbook_title = title_dict['title']+".xls" # 給Excel表格命名
workbook_title = "六級(jí)閱讀短語(yǔ)訓(xùn)練.xls" # 給Excel表格命名
# 獲取煉句
print('\n')
print("正在取讀煉句數(shù)據(jù)丧慈,請(qǐng)等待……")
Text_article = GetTextWeb(book_article_url,s)
article_List = re.findall("{\"status.*?}",Text_article)
sheet = workbook.add_sheet('課程內(nèi)容') #添加sheet
head = [ '內(nèi)容', '解釋']
for h in range(len(head)):
sheet.write(0, h, head[h]) #把表頭寫(xiě)到Excel里面去
m = 1 #Excel開(kāi)始寫(xiě)入的位置
n = 1 #Excel開(kāi)始寫(xiě)入的位置
for article in article_List:
article_dict = json.loads(article)
article_id = article_dict['article_id']
article_id_url = book_article_url+"/"+str(article_id)
Text_article_id = GetTextWeb(article_id_url,s)
content_article_1 = re.findall(" {\"zh-CN\": {\"content.*?}",Text_article_id)
for content1 in content_article_1:
content1 = content1[len("{\"zh-CN\":")+2:]
content_dict_1 = json.loads(content1)
sheet.write(m, 1, content_dict_1['content'])
m += 1
content_article_2 = re.findall("(\"audio_name.*?), \"audio_urls",Text_article_id)
if content_article_2 == []:
content_article_2 = re.findall("(\"content\".*?\"),",Text_article_id)
for i in content_article_2:
if i[len("\"content\": \"")] == "\\":
content_article_2.remove(i)
for i in content_article_2:
if i[len("\"content\": \"")] == "\\":
content_article_2.remove(i)
for content2 in content_article_2:
content2 = "{"+content2+"}" #轉(zhuǎn)成字典
content_dict_2 = json.loads(content2)
sheet.write(n, 0, content_dict_2['content'])
n += 1
# 獲取單詞和短語(yǔ)
print('\n')
print("正在取讀單詞和短語(yǔ)數(shù)據(jù),請(qǐng)等待……")
Text_phrase = GetTextWeb(book_phrase_url,s)
phrase_List = re.findall("{\"content.*?}",Text_phrase)
sheet = workbook.add_sheet('單詞和短語(yǔ)') #添加sheet
head = [ '內(nèi)容', '解釋']
for h in range(len(head)):
sheet.write(0, h, head[h]) #把表頭寫(xiě)到Excel里面去
j = 1 #Excel開(kāi)始寫(xiě)入的位置
for phrase in phrase_List:
phrase_dict = json.loads(phrase)
sheet.write(j, 0, phrase_dict['content'])
sheet.write(j, 1, phrase_dict['definition'])
j += 1
workbook.save(workbook_title)
print('\n')
print('寫(xiě)入excel成功')
print("文件位置:和代碼在同一個(gè)文件夾")
print('\n')
input("煉句取讀完畢主卫,點(diǎn)擊回車(chē)退出")
最后補(bǔ)充:爬取個(gè)人單詞書(shū)
方式和煉句是完全一致的逃默,就是網(wǎng)址不同
網(wǎng)址后面有一個(gè)&_=1559700584497
,這個(gè)是個(gè)時(shí)間戳(寫(xiě)代碼的時(shí)候可以不加簇搅,也能獲取數(shù)據(jù))
url = 'https://www.shanbay.com/api/v1/bdc/library/today/?page=1'
word = s.get(url) # 這里換成get了完域,剛剛是s.post
print(word.text)
這時(shí)候就能看到對(duì)應(yīng)單詞的拼寫(xiě)、發(fā)音瘩将、解釋等等
比如anecdotal吟税,它的數(shù)據(jù),和網(wǎng)頁(yè)顯示一致
同樣姿现,系統(tǒng)儲(chǔ)存的時(shí)候肠仪,都是編碼\u02cc\
這種,轉(zhuǎn)成文字就好啦~
你可以點(diǎn)Preview
备典,一個(gè)單詞异旧,里面有發(fā)音、中英文解釋提佣、例句等等
你需要哪些吮蛹,就獲取哪些
具體數(shù)據(jù)清洗荤崇,這里不廢話了,之前操作都講過(guò)啦~
附:參考網(wǎng)頁(yè)
爬蟲(chóng)(抓取靜態(tài)頁(yè)面和動(dòng)態(tài)頁(yè)面的區(qū)別潮针,get請(qǐng)求和post請(qǐng)求的區(qū)別):https://blog.csdn.net/Spencer_q/article/details/82631154
扇貝自動(dòng)打卡Python腳本(Python3)
http://www.reibang.com/p/284499d5e8b5
如何查看接口术荤?
https://blog.csdn.net/meiceatcsdn/article/details/79999439
python爬蟲(chóng)如何POST request payload形式的請(qǐng)求
https://blog.csdn.net/zwq912318834/article/details/79930423