1

我正在尝试使用 Ruby 和 HTTParty 在 Wikia 上的论坛上发帖。没有可用的文档,因为该过程似乎涉及 Wikia 的内部 API,所以我一直在尝试使用 Chrome 的开发工具来查看正在发出的请求。

据我所知,当用户尝试向论坛上的某个主题发表评论时,会向 .wikia.com/wikia.php 发送一个带有以下参数的 POST 请求:

  • 控制器=WallExternal
  • 方法=replyToMessage
  • parent=(父线程id,例如1036301)
  • body="正在发送的消息"
  • 令牌=编辑令牌*

该过程需要一个编辑令牌,我使用普通的 Mediawiki API 检索该令牌。我遇到的问题是我得到了回应

“您的登录会话似乎有问题;此操作已被取消,以防止会话劫持。返回上一页,重新加载该页面,然后重试。”

使用错误消息的谷歌搜索只会产生在尝试正常登录时出现此错误的人,这在这种情况下不是问题。

我认为问题可能在于请求中未设置用户的标头,因为我认为不允许匿名编辑者发布响应;由于 Mediawiki 文档说未登录的用户会获得“+\”的编辑令牌,因此情况似乎并非如此。

我尝试使用的代码是:

    @api = MediaWiki::Gateway.new 'http://example.wikia.com/api.php'
    @api.login('username', 'password')
    @headers = {
      'User-Agent' => 'example',
      'Cookie' => @api.cookies.map { |k, v| "#{k}=#{v};" }.join(' ')
    }

    query = HTTParty.post('http://example.wikia.com/api.php',
      :body => {
        'action' => 'query',
        'prop' => 'info|revisions',
        'intoken' => 'edit',
        'titles' => 'Thread:2219',
        'format' => 'json'
      },
      :headers => @headers
    )

    token = JSON.parse(query.body)
    token = token["query"]["pages"]["-1"]["edittoken"]

    query = HTTParty.post('http://example.wikia.com/wikia.php',
      :body => {
        'controller' => 'WallExternal',
        'method' => 'changeThreadStatus',
        'format' => 'json',
        'msgid' => '2219',
        'newState' => 'close'
      },
      :headers => @headers
    )

Wikia 目前使用的是 Mediawiki 1.19.24,这就是为什么检索编辑令牌的方法是旧版本的原因。

这主要是一种爱好,我也不是很有经验。我首先在 Wikia 论坛上问了这个问题,一位用户建议我来这里。感谢您的任何帮助,您可以提供。

4

1 回答 1

1

您看到与 CSRF(跨站点请求伪造)相关的错误,因为您无法正确使用“令牌”。

这可能是 MediaWiki 网站创建者有意为之。除非您传递正确的令牌,否则您将无法进行 POST,这表明表单是从正确的 HTML 页面源提交的。此令牌源自服务器,您可能很难将其提取以用于您的 HTTParty 请求。不过,您可以环顾 DOM 以找到一些价值。

我可能会建议使用 Selenium 作为替代方案。由于这使用了适当的浏览器实例,因此您不必处理解析 HTML 响应和制作自定义帖子。相反,您可以编写代码来访问 wikia 站点、登录并提交“新帖子”表单。

请记住,有时网站有保护措施以避免以这种方式自动化。如果您发现发生这种情况(例如,您无法使用 Selenium 登录),在 selenium 代码中放置断点,在浏览器周围单击,然后移过断点以运行更多代码会很有帮助。

话虽如此,既然有一个 MediaWiki API,那么尽可能多地使用该接口可能是一个更好的主意。也就是说,如果 gem 可以满足您的需求,则可能不需要使用 HTTP 客户端或无头浏览器。

于 2016-05-05T20:12:42.303 回答