4

我有一个网页,它要求用户输入一段文本,然后对其执行一些操作。为了向懒惰的用户演示它,我想添加一个“我感到幸运”按钮,该按钮将从维基百科中获取一些随机文本并填充输入。

如何使用 Javascript 从随机的 Wikipedia 文章中获取文本序列?

我发现了一些使用Wikipedia API获取解析文章的示例,但它们往往是服务器端的。我正在寻找一种完全从客户端运行并且不会被同源策略破坏的解决方案。

注意随机胡言乱语是不够的;我需要人类可读的有意义的句子。

4

1 回答 1

11

我的答案建立在此处建议的技术之上。

棘手的部分是制定正确的查询字符串:

http://en.wikipedia.org/w/api.php?action=query&generator=random&prop=extracts&exchars=500&format=json&callback=onWikipedia

  • generator=random选择一个随机页面
  • prop=extractsexchars=500检索 500 个字符的提取
  • format=json返回 JSON 格式的数据
  • callback=导致该数据被包装在一个函数调用中,因此它可以像任何其他数据一样被处理<script>并注入您的页面(请参阅JSONP),从而绕过跨域障碍。
  • requestid可以选择添加,每次使用一个新值,以避免来自浏览器缓存的陈旧结果(IE9 中需要)

查询提供的页面看起来像这样(为了便于阅读,我添加了空格):

onWikipedia(
  {"query":
    {"pages":
      {"12362520":
        {"pageid":12362520,
         "ns":0,
         "title":"Power Building",
         "extract":"<p>The <b>Power Building<\/b> is a historic commercial building in
                    the downtown of Cincinnati, Ohio, United States. Built in 1903, it
                    was designed by Harry Hake. It was listed on the National Register
                    of Historic Places on March 5, 1999. One week later, a group of
                    buildings in the northeastern section of downtown was named a
                    historic district, the Cincinnati East Manufacturing and Warehouse
                    District; the Power Building is one of the district's contributing
                    properties.<\/p>\n<h2> Notes<\/h2>"
  } } } }
)

当然,您每次都会得到不同的文章。

这是一个完整的工作示例,您可以在 JSBin 上试用。

<HTML><BODY>

  <p><textarea id="textbox" style="width:350px; height:150px"></textarea></p>
  <p><button type="button" id="button" onclick="startFetch(100, 500)">
    Fetch random Wikipedia extract</button></p>

  <script type="text/javascript">

    var textbox = document.getElementById("textbox");
    var button = document.getElementById("button");
    var tempscript = null, minchars, maxchars, attempts;

    function startFetch(minimumCharacters, maximumCharacters, isRetry) {
      if (tempscript) return; // a fetch is already in progress
      if (!isRetry) {
        attempts = 0;
        minchars = minimumCharacters; // save params in case retry needed
        maxchars = maximumCharacters;
        button.disabled = true;
        button.style.cursor = "wait";
      }
      tempscript = document.createElement("script");
      tempscript.type = "text/javascript";
      tempscript.id = "tempscript";
      tempscript.src = "http://en.wikipedia.org/w/api.php"
        + "?action=query&generator=random&prop=extracts"
        + "&exchars="+maxchars+"&format=json&callback=onFetchComplete&requestid="
        + Math.floor(Math.random()*999999).toString();
      document.body.appendChild(tempscript);
      // onFetchComplete invoked when finished
    }

    function onFetchComplete(data) {
      document.body.removeChild(tempscript);
      tempscript = null
      var s = getFirstProp(data.query.pages).extract;
      s = htmlDecode(stripTags(s));
      if (s.length > minchars || attempts++ > 5) {
        textbox.value = s;
        button.disabled = false;
        button.style.cursor = "auto";
      } else {
        startFetch(0, 0, true); // retry
      }
    }

    function getFirstProp(obj) {
      for (var i in obj) return obj[i];
    }

    // This next bit borrowed from Prototype / hacked together
    // You may want to replace with something more robust
    function stripTags(s) {
      return s.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, "");
    }
    function htmlDecode(input){
      var e = document.createElement("div");
      e.innerHTML = input;
      return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
    }

  </script>

</BODY></HTML>

一个缺点generator=random是您经常会得到不是实际文章的讨论页面或生成的内容。如果有人可以改进查询字符串以将其限制为高质量的文章,那就太好了!

于 2013-03-08T12:08:03.907 回答