在上标记帖子时获取“您无权标记此帖子”

2024-04-27 00:51:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试开发一个机器人,它可以在堆栈溢出时标记文章。你知道吗

from stackoverflow import StackOverflow
aaa = StackOverflow()
aaa.login("some email", "some password")
aaa.login_site()
response = aaa.add_flag(random_answer, "AnswerNotAnAnswer")
print(response.json())

当然,您希望替换.login()call中的电子邮件和密码,并用真实的应答ID替换random_answer

我得到的结果是:

{'Success': False, 'Message': 'You do not have permission to flag this post', 'ResultChangedState': False, 'Outcome': 2}

我还尝试用浏览器登录并手动标记一篇文章。响应(在F12控制台中)正确:

{"Success":true,"Message":"Thanks, we'll take a look at it","FlagType":17,"ResultChangedState":false,"Outcome":0}

简而言之,我尝试使用Stack Exchange OpenID登录,登录到Stack Overflow,并向/flags/posts/<post_id>/add/<flag_type>发送POST请求。你知道吗


下面是代码的一部分(MCVE),文件名当然是stackoverflow.py。你知道吗

import requests
from bs4 import BeautifulSoup

class StackOverflow:
    def __init__(self):
        self.session = requests.Session()
        self.session.headers.update({
            "User-Agent": "StackOverflow/0.dev (+/dev/null)",
        })
        self.host = "stackoverflow.com"
        self.root = "https://" + self.host
        self.fkey = None

    def get(self, url, data=None, headers=None, root=True):
        if root:
            url = self.root + url
        return self.session.get(url, data=data, headers=headers, timeout=5.0)

    def post(self, url, data=None, headers=None, root=True):
        if root:
            url = self.root + url
        return self.session.post(url, data=data, headers=headers, timeout=5.0)

    def get_soup(self, url, data=None, headers=None, root=True):
        response = self.get(url, data, headers, root)
        return BeautifulSoup(response.text, "html.parser")

    def login_site(self):
        return self._login_openid(
            'https://{}/users/login?returnurl=%2F'.format(self.host),
            'https://{}/users/authenticate'.format(self.host),
            {
                'oauth_version': "",
                'oauth_server': "",
                'openid_identifier': "https://openid.stackexchange.com/",
            })

    def login(self, email, password):
        return self._login_openid(
            'https://openid.stackexchange.com/account/login',
            'https://openid.stackexchange.com/account/login/submit',
            {'email': email, 'password': password})

    def _login_openid(self, fkey_url, post_url, data):
        fkey_soup = self.get_soup(fkey_url, root=False)
        fkey_input = fkey_soup.find('input', {'name': 'fkey'})
        if not fkey_input:
            raise ValueError("fkey not found")
        self.fkey = fkey_input['value']

        data['fkey'] = self.fkey
        response = self.post(post_url, data=data, root=False)
        return response

    def add_flag(self, post_id, flag_type="AnswerNotAnAnswer"):
        response = self.post("/flags/posts/{}/add/{}".format(post_id, flag_type), data={
            'fkey': self.fkey,
        }, headers={
            'Origin': "https://stackoverflow.com",
            'Referer': "https://stackoverflow.com/",
        }, root=True)
        return response

Tags: httpsselfnoneurldatareturnresponsedef