<Project-2 Twitter> Flask: Twitter API Oauth 2.0 验证 在网页上发贴

这两周正在学python,第二次拼接 code 。最终目标是发贴,做个美食,中国游的账号。

laptop: windows 11 home. 

项目结构:

app.py 主程序

config.ini  这里存所有的 keys Tokens 还有 callback url

目录 Templates 用于存 index.html

目录 static 存放 script.js 与  style.css 幻想着漂亮的界面与功能

干这活儿,就两步:

第一步 有个laptop 注册个发堆账号 x稻糠母   稻糠母 = .com

第二步 注册 twitter 开发平台账号 https://developer.x.com/enx稻糠母https://developer.x.com/en

我使用的是:自由计划(free plan)功能就几个:发贴、删帖、转发    第二天结束从 Oauth 1.0a 又回到原点,在这里做个笔记。

前期准备

安装 Python ,  还有以下必要的库  pip install 库名
  • hashlib, base64, os:生成 code_verifiercode_challenge,用于 OAuth 2.0 PKCE 流程。
  • requests:用于与 Twitter API 进行 HTTP 请求。
  • configparser:用于从 config.ini 文件读取配置。
  • OAuth1:用于 OAuth 1.0a 认证(用于媒体上传)。
  • Flask:创建 Web 应用。
  • BeautifulSoup:用于解析 HTML(目前没有使用)。

目录结构

Twitter/                     # 项目根目录
│
├── app.py                   # Flask 应用程序主文件,负责展示RSS内容
├── config.ini               # 存储API密钥等配置信息的文件
├── static/                  # 静态文件目录
│   ├── style.css            # 存储CSS样式文件
│   └── script.js            # JavaScript
│
└── templates/               # Flask HTML 模板文件夹
    └── index.html           # 网页展示的HTML模板

目录说明:

  1. Twitter/:项目根目录,包含应用的主要文件。
  2. app.py:Flask 应用的核心文件,运行时会启动本地服务器,通过网页展示 RSS 内容,并执行 CSV 文件的读取和自动更新操作。
  3. config.ini:用于存储 API 密钥等敏感信息。
  4. static/:存储静态文件,如 CSS 和 JavaScript 文件,负责网页的样式和功能实现。
  5. templates/:Flask 的 HTML 模板文件夹。

主程序 app.py

app.py 代码:

import hashlib
import base64
import os
import requests
import configparser
from requests_oauthlib import OAuth1
from flask import Flask, request, render_template, jsonify, redirect, url_for, session
from bs4 import BeautifulSoup

# 创建 Flask 应用
app = Flask(__name__)

# 定义上传媒体的函数
def upload_media_to_twitter(media_file, media_type):
    # 媒体上传 URL
    url = "https://upload.twitter.com/1.1/media/upload.json"
    files = {'media': media_file}
    data = {
        'media_category': 'tweet_image' if media_type == 'image' else 'tweet_video'
    }

    # 获取 OAuth 认证信息
    access_token = session.get('access_token')
    headers = {
        'Authorization': f'Bearer {access_token}'
    }

    try:
        # 发送上传请求
        response = requests.post(url, headers=headers, files=files, data=data)
        response.raise_for_status()

        # 从响应中提取 media_id
        media_id = response.json().get('media_id_string')
        return media_id
    except requests.exceptions.RequestException as e:
        print(f"Error uploading media: {e}")
        print(f"Response content: {response.content}")
        raise e



# 读取 config.ini 文件中的 Twitter API 凭证
def load_config():
    config = configparser.RawConfigParser()
    try:
        config.read('config.ini')
        return config
    except Exception as e:
        print(f"Failed to load config.ini: {str(e)}")
        return None
    
config = load_config()

# 从配置文件中获取 secret_key 和 Twitter API 凭证
app.secret_key = config.get('flask', 'secret_key')

consumer_key = config.get('twitter', 'consumer_key')
consumer_secret = config.get('twitter', 'consumer_secret')
client_id = config.get('twitter', 'client_id')
client_secret = config.get('twitter', 'client_secret')
access_token = config.get('twitter', 'access_token')
access_token_secret = config.get('twitter', 'access_token_secret')
redirect_url = config.get('twitter', 'redirect_url')  
scopes = "tweet.read tweet.write users.read offline.access"


# 创建 OAuth 1.0a 认证对象
auth = OAuth1(consumer_key, consumer_secret, access_token, access_token_secret)

#OAuth 2.0 登录部分登录部分

# 生成 code_verifier 和 code_challenge
def generate_code_verifier_and_challenge():
    code_verifier = base64.urlsafe_b64encode(os.urandom(32)).rstrip(b'=').decode('utf-8')
    code_challenge = hashlib.sha256(code_verifier.encode('utf-8')).digest()
    code_challenge = base64.urlsafe_b64encode(code_challenge).rstrip(b'=').decode('utf-8')
    return code_verifier, code_challenge

code_verifier, code_challenge = generate_code_verifier_and_challenge()


# 生成授权 Oauth 2.0 URL 
def build_auth_url(client_id, redirect_url, scopes, code_challenge):
    auth_url = (
        f"https://twitter.com/i/oauth2/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_url}&"
        f"scope={scopes}&state=state&code_challenge={code_challenge}&code_challenge_method=S256"
    )
    return auth_url


# 在使用之前生成 auth_url

auth_url = build_auth_url(client_id, redirect_url, scopes, code_challenge)
print(f"Auth URL: {auth_url}") # 调试用,可以直接访问该 URL


@app.route('/')
def index():
    access_token = session.get('access_token')
    if not access_token:
        return redirect(auth_url)  # 如果没有 access_token,重定向到 Twitter 授权页面
    return render_template('index.html', auth_url=auth_url, access_token=access_token)


@app.route('/callback')
def callback():
    code = request.args.get('code')
    if not code:
        return "Error: No authorization code provided", 400
    
    print(f"Authorization code received: {code}")

    try:
        access_token = get_access_token(code)
        session['access_token'] = access_token  # 将 access_token 存储在会话中
        return redirect(url_for('index'))  # 重定向到主页
    except Exception as ex:
        return f"An error occurred: {str(ex)}", 500

@app.route('/fetch_content', methods=['POST'])
def fetch_content():
    url = request.json.get('url')
    if not url:
        return jsonify({'error': 'No URL provided'}), 400
    
    try:
        response = requests.get(url)
        response.raise_for_status()
        response.encoding = 'utf-8'
        
        soup = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值