3

How do I find the total number of questions and answers written by a user across all Stack Exchange sites? A user's stackexchange.com profile page's "account" tab lists the number of questions and answers by site. How do I see the total number of questions and the total number of answers across all sites?

0

2 Answers 2

5

You can use the API

Stack Exchange API has a dedicated endpoint for returning information about network users when given a list user account ids (note that this is not the id you see on the network sites when opening someone's profile page - it is the one found in the network profile): /users/{ids}/associated.

For an interactive experience, try playing around with the snippet below (note that the API has a daily limit of 10 000 requests per IP even with the key so there is a slight chance of running out of quota for the day):

Badge counts added to match Sebastian Simon's answer

const API_BASE = "https://api.stackexchange.com";
const API_VER = 2.3;
const API_KEY = "zhhhBNmsqZLZ967tc2dn8w((";

const getUserAccounts = async(id, {
  page = 1,
  ...rest
}) => {
  const url = new URL(`${API_BASE}/${API_VER}/users/${id}/associated`);
  url.search = new URLSearchParams({
    page: page.toString(),
    ...rest,
  }).toString();

  const res = await fetch(url.toString());
  if (!res.ok) return [];

  const {
    items = [], has_more = false, backoff
  } = await res.json();

  if (backoff) {
    await delay(backoff * 1e3);
    return getUserAccounts(id, {
      page,
      ...rest
    });
  }

  if (has_more) {
    items.push(...(await getUserAccounts(id, {
      page: page + 1,
      ...rest,
    })));
  }

  return items;
};

const makeCell = (content) => {
  const td = document.createElement("td");
  td.append(content);
  return td;
};

const makeRow = (columns) => {
  const tr = document.createElement("tr");
  const cells = columns.map(makeCell);
  tr.append(...cells);
  return tr;
};

const makeLink = (url, label) => {
  const a = document.createElement("a");
  a.target = "_blank";
  a.href = url;
  a.innerText = label;
  return a;
};

window.addEventListener("load", () => {

  const input = document.getElementById("account_id");

  const submit = document.getElementById("search");
  submit.addEventListener("click", async() => {
    const {
      value: accountId
    } = input;

    const report = document.querySelector("#preview > tbody");

    const accounts = await getUserAccounts(accountId, {
      key: API_KEY,
      filter: "*AXic)yfHtd",
    });

    const rows = accounts
      .sort((a, b) => b.answer_count - a.answer_count)
      .map(({
        account_id,
        answer_count,
        question_count,
        site_name,
        site_url,
        user_id,
        badge_counts
      }) => makeRow([
        makeLink(`${site_url}/users/${user_id}`, site_name),
        question_count,
        answer_count,
        Object.entries(badge_counts).map(([t,c]) => `${c} ${t}`).join(", ")
      ]));

    report.querySelectorAll("tr").forEach((r) => r.remove());
    
    const totals = accounts.reduce((a, { 
      answer_count,
      question_count,
      badge_counts: { bronze, silver, gold }
    }) => {
      a[1] += question_count;
      a[2] += answer_count;
      
      const [,,,badges] = a;
      badges[0] += bronze,
      badges[1] += silver,
      badges[2] += gold
      return a;
    }, ["Network-wide",0,0, [0,0,0]]);
    
    const [,,,[sn, ag, au]] = totals;
    totals[3] = `${sn} bronze, ${ag} silver, ${au} gold`;
    
    const total = makeRow(totals);
    report.append(total, ...rows);

    report.closest("table").classList.remove("hidden");
  });

});
label {
  display: block;
  font-weight: 600;
}

caption,
label {
  font-weight: 600;
  margin-bottom: 0.5vh;
}

table {
  margin-top: 4vh;
  border-collapse: collapse;
}

th,
td {
  padding: 2vh 2vw;
  border: 1px solid lightgray;
}

.hidden {
  display: none;
}
<form>
  <label for="account_id">User Account Id</label>
  <input id="account_id" type="text" title="Account Id" placeholder="12345" value="15810379" />
  <button id="search" type="button">Get Info</button>
</form>

<table id="preview" class="hidden" cellspacing="0">
  <caption>Stack Exchange Post Activity</caption>
  <thead>
    <tr>
      <th rowspan="2">Account</th>
      <th>Questions</th>
      <th>Answers</th>
      <th>Badges</th>
    </tr>
  </thead>
  <tbody>
  </tbody>
</table>

0
2

One option is to do this with JavaScript (via DOM traversal):

  1. Go to your accounts page or any other network profile accounts page,

  2. Press F12 to open your browser console,

  3. Copy-paste the following JavaScript code into it (works in Chrome 80+, Edge 80+, Firefox 74+):

    const badgeNames = {
        "badge1": "goldBadges",
        "badge2": "silverBadges",
        "badge3": "bronzeBadges"
      };
    
    console.table(Array.from(document.querySelectorAll(".account-container .account-number, .account-container .badgecount"), ({ textContent: value, nextElementSibling: statKey, previousElementSibling: badgeKey }) => [ // Destructure each element that has a count of something to the count itself and its neighboring elements.
        statKey?.textContent?.trim() // The “unit” of various stats is written after the count.
          ?? badgeNames[badgeKey?.className], // For badges, we’re looking for an (invisible) element before the count.
        Number(value.split(",").join("")) || 0 // Remove commas, convert to number, special handling for Area 51 where the “number” is “-”. Replace `.split(",").join("")` by `.replaceAll(",", "")` in supporting browsers.
      ])
      .filter(([ key ]) => key) // If there are no badges, no key can be produced; remove these cases.
      .reduce((result, [ key, value ]) => {
        result[key] += value;
    
        return result;
      }, {
        reputation: 0,
        goldBadges: 0,
        silverBadges: 0,
        bronzeBadges: 0,
        questions: 0,
        answers: 0
      }));
    
  4. See the result printed in the console in a table layout: in your case, it looks like this:

    (Position) Value
    reputation 42343
    goldBadges 11
    silverBadges 146
    bronzeBadges 581
    questions 812
    answers 283

I’ve also included the badge counts and the reputation counts, although adding up reputation may be … difficult to interpret.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .