Facebook 데이터와 JavaScript로 쓸모없는 친구를 버리다

23968 단어 webdevjavascript
우정은 유지하기 어렵다.이렇게 많은 정력이 우정을 유지하는 데 낭비되고, 이런 우정은 사실상 어떠한 실질적인 보답도 가져오지 않을 것이다.나는 "물론, 나는 유치원에서 그녀를 알게 되었다. 그녀는 나를 내 아내에게 소개했고, 내가 쫓겨났을 때, 그녀는 나로 하여금 그녀의 곳에서 6개월을 살게 했지만, 이것이 정말 가치 있는 우정인가?"라고 생각했다.
나는 어떤 친구를 버릴지 결정해야 한다.근데 기준이 뭐예요?보다지력돈.
물론 개인의 가치는 주관적이다.경험을 기준으로 할 방법이 없지, 그렇지?틀렸어.친구의 가치를 평가하는 믿을 만한 방법은 페이스북 메신저에서 받은 표정 반응량이다.

더 많은 웃음소리는 이것이 바로 재미있는 친구라는 것을 의미한다.가장 분노한 반응은 논쟁적인 반응이다.등등이해하기 쉽다
인공 계수는 불가능하다.나는 자동으로 이 임무를 완성해야 한다.

데이터 가져오기


채팅 삭제가 너무 느려요.API가 하나 있지만 여기에 해당하는지 모르겠습니다.그것은 보기에 매우 무섭다. 문서에 글이 너무 많다.나는 마침내 필요한 데이터를 얻는 방법을 찾았다.

Facebook lets me download all the deeply personal information여 년 동안 그들은 읽기 쉬운 JSON 형식으로 나의 정보를 수집했다.그들은 매우 좋다!필요한 데이터(메시지)만 선택하고 최소한의 이미지 품질을 선택하여 아카이브를 최소화합니다.그것은 생성되기까지 몇 시간, 심지어 며칠이 걸릴 수도 있다.
다음 날, 나는 아카이브가 사용 가능한 복사본 탭에서 다운로드할 준비가 되어 있다는 이메일을 받았다.zip 파일에는 다음과 같은 구조가 있습니다.
messages
├── archived_threads
│   └── [chats]
├── filtered_threads
│   └── [chats]
├── inbox
│   └── [chats]
├── message_requests
│   └── [chats]
└── stickers_used
    └── [bunch of PNGs]
내가 관심 있는 목록은 inbox이다.[chats] 디렉토리에는 다음과 같은 구조가 있습니다.
[ChatTitle]_[uniqueid]
├── gifs
│   └── [shared gifs]
├── photos
│   └── [shared photos]
├── videos
│   └── [shared videos]
├── files
│   └── [other shared files]
└── message_1.json
내가 필요로 하는 데이터는 message_1.json이다._1 접미사가 왜 필요한지 모르겠어요.내 파일에는 message_2.json 또는 그 어떠한 변체도 없다.
예를 들어 내가 사용하고 싶은 채팅 이름이'나체 배구 파트너'라면 전체 경로는 messages/inbox/NudeVolleyballBuddies_5tujptrnrm/message_1.json과 유사할 것이다.
이 파일들은 상당히 커질 수 있습니다. 따라서 좋아하는 IDE가 그것을 보자마자 쓰러지면 놀라지 마십시오.내가 분석하고 싶은 채팅은 약 5년 동안 백만 줄이 넘는 JSON이 생겼다.
JSON 파일의 구조는 다음과 같습니다.
{
  "participants": [
    { "name": "Ricardo L" },
    { "name": "etc..." }
  ],
  "messages": [
    " (list of messages...) " 
  ],
  "title": "Nude Volleyball Buddies",
  "is_still_participant": true,
  "thread_type": "RegularGroup",
  "thread_path": "inbox/NudeVolleyballBuddies_5tujptrnrm"
}
messages에 주목하고 싶습니다.각 메시지에는 다음 형식이 있습니다.
{
  "sender_name": "Ricardo L",
  "timestamp_ms": 1565448249085,
  "content": "is it ok if i wear a sock",
  "reactions": [
    {
      "reaction": "\u00f0\u009f\u0098\u00a2",
      "actor": "Samuel L"
    },
    {
      "reaction": "\u00f0\u009f\u0098\u00a2",
      "actor": "Carmen Franco"
    }
  ],
  "type": "Generic"
}
내가 원하는 걸 찾았어!여기에 모든 반응이 열거되어 있다.

JavaScript에서 JSON 읽기


이 작업에 FileReader API을 사용합니다.
<input type="file" accept=".json" onChange="handleChange(this)">
function handleChange(target) {
  const reader = new FileReader();
  reader.onload = handleReaderLoad;
  reader.readAsText(target.files[0]);
}

function handleReaderLoad (event) {
  const parsedObject = JSON.parse(event.target.result);
  console.log('parsed object', parsedObject);
}
페이지에서 파일 입력 필드를 보았습니다. JSON을 선택할 때 해결된 JavaScript 객체가 콘솔에 기록됩니다.길이가 너무 길어서 몇 초가 걸릴지도 몰라요.지금 나는 그것을 어떻게 읽는지 확실히 알아야 한다.

분석 데이터


간단하게 시작합시다.나의 첫 번째 목표는 나의 messages_1.json을 입력으로 하는 것이다. 이와 같은 내용을 출력으로 하는 것이다.
output = [
  {
    name: 'Ricardo L',
    counts: {
      '😂': 10,
      '😍': 3,
      '😢': 4,
    },
  },
  {
    name: 'Samuel L',
    counts: {
      '😂': 4,
      '😍': 5,
      '😢': 12,
    },
  },
  // etc for every participant
]
원본 JSON의 participants 객체는 이미 유사한 형식을 가지고 있습니다.counts 필드만 추가하면 됩니다.
const output = parsedObject.participants.map(({ name }) => ({
  name,
  counts: {},
}))
이제 전체 메시지 목록을 교체하고 반응 계수를 누적해야 합니다.
parsedObject.messages.forEach(message => {
  // Find the correct participant in the output object
  const outputParticipant = output.find(({ name }) => name === message.sender_name)

  // Increment the reaction counts for that participant
  message.reactions.forEach(({ reaction }) => {
    if (!outputParticipant.counts[reaction]) {
      outputParticipant.counts[reaction] = 1
    } else {
      outputParticipant.counts[reaction] += 1
    }
  })
})
기록된 출력은 다음과 같습니다.

나는 이모티콘이 아니라 네 개의 이상한 기호를 얻었다.무슨 좋은 점이 있습니까?

반응 이모티콘 디코딩


나는 메시지를 예로 들었다. 그것은 단지 하나의 반응뿐이었다. 우는 이모티콘(😢). JSON 파일을 검토한 결과
"reaction": "\u00f0\u009f\u0098\u00a2"
이 캐릭터 훈련과 울음 이모티콘은 어떤 관계가 있습니까?
보기에는 그렇지 않을 수도 있지만, 이 문자열은 네 글자 길이가 있다.
  • \u00f0
  • \u009f
  • \u0098
  • \u00a2
  • JavaScript에서 \u은 이스케이프 시퀀스를 나타내는 접두사입니다.이 특수한 전의 서열은 \u에서 시작하여 뒤에 네 개의 16진 숫자와 같다.UTF-16 형식의 유니코드 문자를 나타냅니다.주의: it's a bit more complicated than that, 그러나 본고에서 우리는 모든 내용을 UTF-16로 간주할 수 있다.
    예를 들어, the Unicode hex code of the capital letter S is 0053 .콘솔에 "\u0053"을 입력하여 JavaScript에서 작동하는 방식을 볼 수 있습니다.

    유니코드 테이블을 다시 한 번 보니 the hex code for the crying emoji is 1F622 이 보입니다.이는 네 자리수보다 길기 때문에 \u1F622을 간단하게 사용하면 안 된다.두 가지 해결 방법이 있습니다.
  • UFT-16 surrogate pairs . 이것은 16진수를 두 개의 비교적 작은 4자리 숫자로 나누었다.이 예에서 울음 이모티콘은 \ud83d\ude22을 나타낸다.
  • 은 유니코드 코드를 직접 사용하고 약간 다른 형식을 사용합니다: \u{1F622}.코드를 괄호로 묶는 것을 주의하십시오.
  • JSON에서 모든 반응은 괄호가 없는 네 개의 문자 코드를 사용하고 they're not in the right range 때문에 프록시가 맞을 수 없습니다.
    그럼 얘네는 뭐야?
    우리 한 조 possible encodings for this emoji을 봅시다.이게 익숙해 보여요?

    너무 가까워!이것은 16진수 형식의 UTF-8 인코딩이라는 사실이 증명되었다.그러나 어떤 이유로 모든 바이트는 UTF-16 형식으로 유니코드 문자를 쓴다.
    이 점을 알고 있습니다. \u00f0\u009f\u0098\u00a2에서 \uD83D\uDE22까지 어떻게 합니까?
    각 문자를 바이트로 추출한 다음 바이트를 UTF-8 문자열로 결합합니다.
    function decodeFBEmoji (fbString) {
      // Convert String to Array of hex codes
      const codeArray = (
        fbString  // starts as '\u00f0\u009f\u0098\u00a2'
        .split('')
        .map(char => (
          char.charCodeAt(0)  // convert '\u00f0' to 0xf0
        )
      );  // result is [0xf0, 0x9f, 0x98, 0xa2]
    
      // Convert plain JavaScript array to Uint8Array
      const byteArray = Uint8Array.from(codeArray);
    
      // Decode byte array as a UTF-8 string
      return new TextDecoder('utf-8').decode(byteArray);  // '😢'
    }
    
    이제 정확한 렌더링 결과에 필요한 것이 생겼습니다.

    버릴 친구를 고르다


    나는 매 반응의 횟수에 따라 점수를 계산하고 싶다.변수가 필요합니다.
  • 참여자의 총 메일 수 (T)
  • 참여자가 보낸 총 반응 (SR)
  • 참여자당 전 세계 평균 메일 수(평균)
  • 받은 반응에 대해 나는 몇 가지 분류를 했다.
  • 👍: 승인 (A)
  • 👎: 비승인 (D)
  • 😆 화목하다😍: 긍정 정서(PE)
  • 😢 화목하다😠: 부정적인 감정(NE)
  • 😮: 중립, 나는 그것을 포기할 것이다
  • 최종 공식은 다음과 같습니다.

    결과는 점수가 높을수록 사람이 좋다.Here is an explanation of how I reached this equation.
    JavaScript에서는 다음과 같습니다.
    participants.forEach((participant) => {
      const {
        reactions,
        sentReactionCount,
        messageCount,
      } = participant
    
      const approval = reactions['👍']
      const disapproval = reactions['👎']
      const positiveEmotion = reactions['😆'] + reactions['😍']
      const negativeEmotions = reactions['😢'] + reactions['😠']
    
      const positiveFactor = (2 * approval + 3 * positiveEmotion + sentReactionCount)
      const negativeFactor = (2 * disapproval + 3 * negativeEmotions)
      const totalMessageFactor = Math.abs(messageCount - messageCountAverage) / (messageCountAverage)
    
      participant.score = (positiveFactor - negativeFactor) / totalMessageFactor
    })
    
    정보를 테이블로 표시하여 보다 쉽게 확인할 수 있습니다.

    주: 프라이버시를 고려하여 나는 친구의 실제 이름을 그들의 가정 주소로 바꾸었다.

    안녕히 가세요.


    표를 빠르게 훑어보면, 나는 마침내 내가 내 생활에서 누구를 삭제해야 할지 결정할 수 있다.

    안녕히 계세요, 샘 사촌 형.

    좋은 웹페이지 즐겨찾기