如何獲取在思否「問答」打卡中的完成次數?

linong發表於2022-06-14
已參與了 SegmentFault 思否社群 10 週年「問答」打卡 ,歡迎正在閱讀的你也加入。

最近 「SegmentFault 思否社群 10 週年「問答」打卡」 十分火熱,但是有一個小問題,經常不知道是否完成今天的 KPI,以及小尾巴是否正常新增,那我們今天來做個小工具。

分析

  1. 先開啟個人的問答頁
  2. 查詢是否有單獨拉問答資料的介面。(感謝官方老闆在後期做過優化,直接有介面
    image.png
  3. 右鍵 copy as fetch 我們就可以快樂的使用了
    image.png

改造&迴圈

改造成可以查出所有資料,並且過濾掉不感興趣的資訊(graphql 的就更好了,可惜不是

getAnswers = function(username, page = 1, startTime = new Date('2022-06-01 00:00:00.000').getTime() / 1000){
    return fetch(`https://segmentfault.com/gateway/homepage/${username}/answers?size=20&page=${page}&sort=newest`)
        .then(v=>v.json())
        .then(v=>v.rows)
        .then(async v=>{
            if(v.length === 20 && (v[v.length - 1]?.created || 0) > startTime){
                return v.concat(await getAnswers(username, page + 1, startTime))    
            }else{
                return v.filter(v=>v.created > startTime)
            }

        })
        // .then(console.log)
}
list = [];
getAnswers('linong')
    .then(console.log)

// new Date(1655005451 * 1000).toLocaleString();
// new Date('2022-06-01 00:00:00.000').getTime()

image.png

僅供學習,不要違法喲!

檢視幾個活躍使用者

await getAnswers('hfhan')
    .then(console.log)
await getAnswers('jamesfancy')
    .then(console.log)
await getAnswers('nickw_cn')
    .then(console.log)
await getAnswers('xdsnet')
    .then(console.log)

我們會發現這裡的 username 好像是一個固定值,和使用者名稱是不一樣的,那我們在做一個 url 提取,方便我們不用手動選中

'https://segmentfault.com/u/jamesfancy/answers'.match(/\/u\/([^/]+)/)[1]

image.png

分析如何獲取是否有小尾巴

因為不是 graphql 的,所以上述內容只能有多少回答,如果想檢視小尾巴的新增狀況我們還需要再做一次採集。

通過檢視好像也沒有暴露出有介面,那我們只能直接處理 html 資料了。

xhr = new XMLHttpRequest()
xhr.open('get', 'https://segmentfault.com/q/1010000041964562/a-1020000041964682')
xhr.responseType = 'document'
xhr.send();
xhr.onload = () => console.log(xhr.response, xhr.response.querySelector('[id="1020000041964682"] [href^="https://segmentfault.com/a/1190000041925107"]'))

這樣我們使用選擇器直接判斷回答中是否包含特徵值即可,你猜為什麼我這裡用了 xhr,而不是 fetch 呢?

url 提取 id

'https://segmentfault.com/q/1010000041964562/a-1020000041964682'.match(/\/a-(\d+)$/)[1]

image.png

改造 迴圈

getAnswers = function(username, page = 1, startTime = new Date('2022-06-01 00:00:00.000').getTime() / 1000){
    return fetch(`https://segmentfault.com/gateway/homepage/${username}/answers?size=20&page=${page}&sort=newest`)
        .then(v=>v.json())
        .then(v=>v.rows)
        .then(async v=>{
            if(v.length === 20 && (v[v.length - 1]?.created || 0) > startTime){
                return v.concat(await getAnswers(username, page + 1, startTime))    
            }else{
                return v.filter(v=>v.created > startTime)
            }

        })
        // .then(console.log)
}
checkAnswerExt = async function(url){
    const id = url.match(/\/a-(\d+)$/)[1];
    
    var xhr = new XMLHttpRequest()
    xhr.open('get', `https://segmentfault.com${url}`)
    xhr.responseType = 'document'
    xhr.send();
    return new Promise(function(resolve, reject){
        xhr.onload = () => 
            resolve(
                xhr
               .response
               .querySelector(`[id="${id}"] [href^="https://segmentfault.com/a/1190000041925107"]`)
            )
    })
}
answers = [];
await getAnswers('cowcomic')
    .then(async function(list){
        for(var i = 0; i < list.length; i++){
            answers.push({
                answers: list[i],
                checked: await checkAnswerExt(list[i].url)
            })
        }
    })
    // .then(console.log)
answers

image.png

可以發現,的確是存在沒有小尾巴,這樣補一下即可。

分析資料

這樣我們有了個人問答所有關心的資料,接下來我們可以 groupBy 查出所有沒有小尾巴的資料,然後補一下資料。

也可以按時間維度檢視每天完成量

大功告成。最後再提醒一居,僅供學習,不要違法喲!

相關文章