python简单实践作业答案_python入门实践四:爬取牛客网面试专项练习题及答案
說明:個人練手python用。
操作系統:window10 x64
IDE:Pycharm 2017.2.2
Python版本:3.6.2
目標
牛客網是一個IT筆試面試的平臺,提供了很多題庫,今天我們使用python爬取其中的Java專項練習庫。
步驟
1、接口抓取:如果是爬取網頁,前后端分離的項目可以抓取接口,如果沒有分離,則需要爬取整個網頁然后使用正則篩選。這里我們直接抓取客戶端接口即可。
2、模擬網絡請求,獲取數據(這里是json)
3、json解析,題目格式調整、寫入文件
一、接口抓取
工具:Fiddler
對象:牛客網Android客戶端2.21.3.3091
通過Fiddler發現,獲取專項練習題的接口為:
http://m.nowcoder.com/test/get-all-question?t=02436CC60E649584D5C4BBF57709E5CA&fm=android_app_2.21.3.3091&tid=10716711
這里:
t=02436CC60E649584D5C4BBF57709E5CA應該是用戶身份標識
tid=10716711是本次練習的編號(Java專項練習一共900多道題,每次練習會隨機組卷,組卷數量為5、10、20、30這些,這個tid就是組出的試卷的編號)
使用Fiddler模擬請求,就可以得到該tid對應10道題目的json數據了,由于每次請求tid沒有變化,可以發現多次請求的json結果是一樣的,類似下面的:
{
"data": {
"paper": {
......省略部分
"diffcult": 3,
"questionCount": 10,
......省略部分
},
"allQuestion": [
{
"score": 10,
"shielded": false,
"question": {
"content": "
\n 下列關于構造方法不正確的是:( \n )\n
\n\n 
\n
\n 
\n
"id": 69561,
"title": "下列關于構造方法不正確的是:( )",
"answer": [
{
"content": "類的構造方法和類同名",
"id": 111297,
"type": 0
},
......省略部分
],
......省略部分
},
"pos": 1
},
......省略部分
],
"userAnswers": [
{
"userAnswer": "111300",
"pos": 1
},
......省略部分
]
},
"code": 0,
"msg": "OK"
}
要想不一樣,就需要不一樣的tid了,發現生成tid的接口如下:
POST http://m.nowcoder.com/itest/request-make-paper HTTP/1.1
......省略部分request header
questionCount=10&tagIds=570&t=02436CC60E649584D5C4BBF57709E5CA&fm=android_app_2.21.3.3091&source=1
這是一個post請求,可以發現在request body中的questionCount就是表明了本次組卷試題的數量。
這樣思路就清晰了:
根據request-make-paper接口獲取tid,這里我們指定questionCount為30
根據get-all-question接口,傳入tid參數,獲取此次組卷的30道題的json數據
然后分析這30道題中的字段的含義,解析、存儲即可
二、網絡請求
定義一個方法,用于post請求,返回響應的內容,如下:
def post_json_data(url, request_body):
req = request.Request(url)
# 根據需要設置請求頭,比如模擬瀏覽器請求設置UA、一些身份權限認證字段等都會放到header里
req.add_header('OS', 'Android')
req.add_header('VERSION', '82')
req.add_header('CHANNEL', '360')
req.add_header('User-Agent', 'nowcoder android 2.21.3.3091')
# post請求,添加request body即可
with request.urlopen(req, data=request_body.encode('utf-8')) as f:
if f.status == 200:
result_json = json.loads(f.read())
return result_json
再定義一個方法,用于get請求,返回響應的內容,如下:
def get_json_data(url):
req = request.Request(url)
req.add_header('OS', 'Android')
req.add_header('VERSION', '82')
req.add_header('CHANNEL', '360')
req.add_header('User-Agent', 'nowcoder android 2.21.3.3091')
with request.urlopen(req) as f:
if f.status == 200:
result_json = json.loads(f.read())
return result_json
如果把添加到request header中的這些key-value的參數組成dict,就可以通過外部傳入,方法中遍歷添加,上面兩個方法就可以作為工具方法了。
接下來組裝post請求的request body中的參數
data_make_paper = parse.urlencode([
('questionCount', '30'),
('tagIds', '570'),
('t', '02436CC60E649584D5C4BBF57709E5CA'),
('fm', 'android_app_2.21.3.3091'),
('source', '1')
])
就可以發送網絡請求,獲取響應數據了:
result = post_json_data('http://m.nowcoder.com/itest/request-make-paper', data_make_paper)
url_get_questions = "http://m.nowcoder.com/test/get-all-question" + \
"?t=02436CC60E649584D5C4BBF57709E5CA&fm=android_app_2.21.3.3091&tid=" + \
str(result['data'])
需要注意的是,需要引入request和parse模塊:
from urllib import request,parse
三、json解析,題目格式調整、寫入文件
先定義一個寫入文件的方法,這里我們需要追加的形式寫,也即后面寫入的內容不能覆蓋前面已經寫入的:
def write_text(path, text, mode='a'):
with open(path, mode=mode, encoding="utf-8") as f:
f.write(text)
f.write("
")
mode = 'a'就表示追加的形式寫入。
接下來就是json解析、添加一下格式(如題目編號,選項編號,題與題之間的空行等)、然后寫入文件了,直接看代碼:
all_questions = get_json_data(url_get_questions)['data']['allQuestion']
# 題號信息,由于獲取的題目沒有編號
n = 1
# 提取出來方便修改,如果有明確的題目數量,可以嵌套一層循環來循環獲取n套題。這里我們獲取1套題作為演示
# 之所以寫入到html文件,是因為讀取的題目中含有html的格式信息
questions_name = "第1套.html"
questions_answer_name = "第1套答案.html"
for item_question in all_questions:
# 獲取題干信息
question = item_question['question']
question_type = ['(單選題)', '(不定項選擇題)']
# 寫入題目信息
write_text("C://python_test/"+questions_name, str(n)+". "+question_type[question['type']-1]+question['content'], 'a')
answer = question['answer']
answer_option = ''
index = 0
for item_answer in answer:
# 獲取選項信息
answer_content = item_answer['content']
answer_index_list = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
# 寫入選項信息,加入ABCD等選項編號
write_text("C://python_test/"+questions_name, answer_index_list[index]+". "+answer_content, 'a')
# 獲取type字段的值,為1表示該選項為正確答案
answer_type = item_answer['type']
if answer_type == 1:
# 獲取正確答案
answer_option += answer_index_list[index]
index += 1
# 每題之間留空行
write_text("C://python_test/"+questions_name, '', 'a')
# 寫入答案到另外一個文件中
write_text("C://python_test/"+questions_answer_name, str(n)+"."+'答案: ' + answer_option, 'a')
# 答案之間留空行
write_text("C://python_test/"+questions_answer_name, '', 'a')
# 編號自增
n += 1
注意引入json模塊
import json
python中的json和dict直接對應,非常方便。
留個作業:
通過抓取答題接口,完成題目自動答題,保證每套題都得滿分~
總結
以上是生活随笔為你收集整理的python简单实践作业答案_python入门实践四:爬取牛客网面试专项练习题及答案的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Python面试常用二十题总结
- 下一篇: java 判断请求为 ajax请求_Ja
