cnki-navigate-pages

Navigate CNKI search result pages (next/previous/specific page) or change sort order. Use when user wants to see more results or change sorting.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "cnki-navigate-pages" with this command: npx skills add cookjohn/cnki-skills/cookjohn-cnki-skills-cnki-navigate-pages

CNKI Results Pagination and Sorting

All operations use a single async evaluate_script — no snapshot or wait_for needed.

Arguments

$ARGUMENTS should be one of:

  • next / previous / page N — pagination
  • sort by date / sort by citations / sort by downloads / sort by relevance / sort by comprehensive — sorting

Pagination (single evaluate_script)

Replace ACTION_HERE with "next", "previous", or "page 3":

async () => {
  const cap = document.querySelector('#tcaptcha_transform_dy');
  if (cap && cap.getBoundingClientRect().top >= 0) return { error: 'captcha' };

  const action = "ACTION_HERE";
  const pageLinks = document.querySelectorAll('.pages a');
  const prevMark = document.querySelector('.countPageMark')?.innerText;

  if (action === 'next') {
    const next = Array.from(pageLinks).find(a => a.innerText.trim() === '下一页');
    if (!next) return { error: 'no_next_page' };
    next.click();
  } else if (action === 'previous') {
    const prev = Array.from(pageLinks).find(a => a.innerText.trim() === '上一页');
    if (!prev) return { error: 'no_previous_page' };
    prev.click();
  } else {
    const num = action.replace(/\D/g, '');
    const target = Array.from(pageLinks).find(a => a.innerText.trim() === num);
    if (!target) return { error: 'page_not_found', available: Array.from(pageLinks).map(a => a.innerText.trim()) };
    target.click();
  }

  // Wait for page change
  await new Promise((r, j) => {
    let n = 0;
    const c = () => {
      const mark = document.querySelector('.countPageMark')?.innerText;
      if (mark && mark !== prevMark) r();
      else if (++n > 30) j('timeout');
      else setTimeout(c, 500);
    };
    setTimeout(c, 1000);
  });

  const cap2 = document.querySelector('#tcaptcha_transform_dy');
  if (cap2 && cap2.getBoundingClientRect().top >= 0) return { error: 'captcha' };

  return {
    action,
    total: document.querySelector('.pagerTitleCell')?.innerText?.match(/([\d,]+)/)?.[1] || '0',
    page: document.querySelector('.countPageMark')?.innerText || '?',
    url: location.href
  };
}

Sorting (single evaluate_script)

Replace SORT_HERE with "relevance", "date", "citations", "downloads", or "comprehensive":

async () => {
  const cap = document.querySelector('#tcaptcha_transform_dy');
  if (cap && cap.getBoundingClientRect().top >= 0) return { error: 'captcha' };

  const sortBy = "SORT_HERE";
  const idMap = {
    'relevance': 'FFD', 'date': 'PT',
    'citations': 'CF', 'downloads': 'DFR', 'comprehensive': 'ZH'
  };

  const liId = idMap[sortBy];
  if (!liId) return { error: 'invalid_sort', valid: Object.keys(idMap) };

  const li = document.querySelector('#orderList li#' + liId);
  if (!li) return { error: 'sort_option_not_found' };

  const prevMark = document.querySelector('.countPageMark')?.innerText;
  li.click();

  // Wait for results to refresh (page resets to 1)
  await new Promise((r, j) => {
    let n = 0;
    const c = () => {
      const mark = document.querySelector('.countPageMark')?.innerText;
      if (mark && mark !== prevMark) r();
      else if (++n > 30) j('timeout');
      else setTimeout(c, 500);
    };
    setTimeout(c, 1000);
  });

  return {
    sortBy,
    total: document.querySelector('.pagerTitleCell')?.innerText?.match(/([\d,]+)/)?.[1] || '0',
    page: document.querySelector('.countPageMark')?.innerText || '?',
    activeLi: document.querySelector('#orderList li.cur')?.innerText?.trim(),
    url: location.href
  };
}

Output

Navigated to page {page}. Total {total} results. Results now sorted by {sortBy}.

Tool calls: 1 (evaluate_script only)

Verified selectors

ElementSelectorNotes
Page links.pages anumbers + 上一页/下一页
Current page.pages a.cur
Next pagetext 下一页, class pagesnums
Page counter.countPageMarktext "1/300"
Sort container#sortList (.order-group)
Sort options#orderList liclick to sort
相关度li#FFDdata-sort="FFD"
发表时间li#PTdata-sort="PT"
被引li#CFdata-sort="CF"
下载li#DFRdata-sort="DFR"
综合li#ZHdata-sort="ZH"
Active sort#orderList li.curhas class cur

Captcha detection

Check #tcaptcha_transform_dy element's getBoundingClientRect().top >= 0. Only active when top >= 0 (visible). Pre-loaded SDK sits at top: -1000000px.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

cnki-search

No summary provided by upstream source.

Repository SourceNeeds Review
General

cnki-download

No summary provided by upstream source.

Repository SourceNeeds Review
General

cnki-advanced-search

No summary provided by upstream source.

Repository SourceNeeds Review
General

cnki-journal-search

No summary provided by upstream source.

Repository SourceNeeds Review