星球批量下载文件

查看 24|回复 1
作者:蜗牛很牛   
现在有个问题就是不能一下子获取所有的文件必须挨个加入URL有什么办法么
import requests
import os
import json
import tkinter as tk
from tkinter import messagebox
定义保存配置的文件名
CONFIG_FILE = "config.json"
读取配置
def load_config():
if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, "r") as f:
return json.load(f)
return {}
保存配置
def save_config(session_id, access_token, url):
config = {
"zsxqsessionid": session_id,
"zsxq_access_token": access_token,
"url": url
}
with open(CONFIG_FILE, "w") as f:
json.dump(config, f)
下载文件的函数
def download_files():
config = load_config()
session_id = config.get("zsxqsessionid")
access_token = config.get("zsxq_access_token")
url = config.get("url")
if not session_id or not access_token or not url:
    messagebox.showerror("Error", "请确保已输入所有信息并保存。")
    return
headers = {
    'cookie': f'zsxqsessionid={session_id}; zsxq_access_token={access_token}',
    'accept': 'application/json, text/plain, */*',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36'
}
response = requests.get(url, headers=headers)
if response.status_code != 200:
    messagebox.showerror("Error", f"获取主题失败: {response.status_code}")
    return
data = response.json()
for topic in data.get("resp_data", {}).get("topics", []):
    if "files" in topic.get("talk", {}):
        for file in topic["talk"]["files"]:
            if "file_id" in file:
                file_id = file["file_id"]
                download_url_api = f"https://api.zsxq.com/v2/files/{file_id}/download_url"
                try:
                    download_response = requests.get(download_url_api, headers=headers)
                    download_response.raise_for_status()
                    download_data = download_response.json()
                    if download_data.get("succeeded"):
                        file_url = download_data["resp_data"]["download_url"]
                        file_name = file["name"]
                        file_response = requests.get(file_url, headers=headers)
                        file_response.raise_for_status()
                        if os.path.exists(file_name):
                            base, extension = os.path.splitext(file_name)
                            counter = 1
                            while os.path.exists(file_name):
                                file_name = f"{base}_{counter}{extension}"
                                counter += 1
                        with open(file_name, "wb") as file_obj:
                            file_obj.write(file_response.content)
                        print(f"Downloaded: {file_name}")
                    else:
                        print(f"获取文件 ID {file_id} 的下载链接失败")
                except requests.RequestException as e:
                    print(f"获取文件 ID {file_id} 的下载链接失败: {e}")
保存配置的回调
def save_button_click():
session_id = session_id_entry.get()
access_token = access_token_entry.get()
url = url_entry.get()
save_config(session_id, access_token, url)
messagebox.showinfo("Info", "配置已保存!")
创建 UI
root = tk.Tk()
root.title("下载配置")
tk.Label(root, text="zsxqsessionid:").grid(row=0, column=0)
session_id_entry = tk.Entry(root)
session_id_entry.grid(row=0, column=1)
tk.Label(root, text="zsxq_access_token:").grid(row=1, column=0)
access_token_entry = tk.Entry(root)
access_token_entry.grid(row=1, column=1)
tk.Label(root, text="URL:").grid(row=2, column=0)
url_entry = tk.Entry(root)
url_entry.grid(row=2, column=1)
save_button = tk.Button(root, text="保存配置", command=save_button_click)
save_button.grid(row=3, column=0, columnspan=2)
download_button = tk.Button(root, text="下载文件", command=download_files)
download_button.grid(row=4, column=0, columnspan=2)
加载现有配置
config = load_config()
session_id_entry.insert(0, config.get("zsxqsessionid", ""))
access_token_entry.insert(0, config.get("zsxq_access_token", ""))
url_entry.insert(0, config.get("url", ""))
root.mainloop()

文件, 下载链接

Osk   

当然是先研究下文件的url是咋来的了,我几年前写过一个,可以给你参考,当时api版本还是 v1
[Java] 纯文本查看 复制代码import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
public class ZSXQ_downloader {
    static Map config_map = new TreeMap();
    private static void init() throws Exception{
        //这两项是关键参数,不能变更
        config_map.put("url_pattern","https://api.zsxq.com/v1/groups/%s/%s?scope=all&count=20");
        config_map.put("Header",new File("header"));
        //适应习惯表达
        config_map.put("month",Calendar.getInstance().get(Calendar.MONTH)+1);
        config_map.put("local_dir","");
        config_map.put("qid","824552281252");
        config_map.put("download",false);
        config_map.put("need_img",false);
        config_map.put("need_file",false);
        config_map.put("debug",false);
        File config = new File("config.json");
        //如果配置文件不存在,把默认值写进去
        if(!config.exists()) {
            JSONObject jconfig = new JSONObject();
            for(String key:config_map.keySet()){
                jconfig.put(key,config_map.get(key));
            }
            JSONArray default_author = new JSONArray();
            default_author.add(48582851245248L);
            jconfig.put("accept_author_id",default_author);
            jconfig.put("block_topics_id",new JSONArray());
            FileOutputStream fos = new FileOutputStream(config);
            fos.write(jconfig.toString().getBytes(StandardCharsets.UTF_8));
            return;
        }
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(config), StandardCharsets.UTF_8));
        String str; StringBuilder sb = new StringBuilder();
        while((str = br.readLine())!=null){
            sb.append(str);
        }
        JSONObject conf = JSONObject.parseObject(sb.toString());
        for(String key:conf.keySet()){
            //防止覆盖关键字段
            if(key.equals("url_pattern")||key.equals("Header")) continue;
            config_map.put(key,conf.get(key));
        }
    }
    public static void main(String[] args) throws Exception{
        init();
        JsonProcessor j = new JsonProcessor(config_map);
        String result = j.read_in().generate_MD();
        FileOutputStream fos = new FileOutputStream(new File("output.md"));
        fos.write(result.getBytes());
        fos.close();
        if((boolean)config_map.get("download")){
            j.downloadFile();
        }
    }
}
[Java] 纯文本查看 复制代码import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
class JsonProcessor {
    private Map config_map;
    private String url_pattern;
    private File Header;
    private int month;
    private JSONArray data;
    public JsonProcessor(Map config_map){
        this.config_map = config_map;
        this.url_pattern = (String)config_map.get("url_pattern");
        this.Header = (File)config_map.get("Header");
        //为了配合 Calendar类从0开始表示月份,我们将按照表达习惯传入的month-1
        this.month = (Integer)config_map.get("month")-1;
    }
    public String generate_MD() throws Exception{
        return generate_MD(data);
    }
    public JsonProcessor read_in() throws Exception{
        String topic_url = String.format(url_pattern,config_map.get("qid"),"topics");
        data = read_in(topic_url,month);
        return this;
    }
    public void downloadFile() throws Exception{
        String file_url = String.format(url_pattern,config_map.get("qid"),"files");
        String dl_path = new File("").getAbsolutePath() + "\\星球文件\\";
        if(!new File(dl_path).exists()){
            new File(dl_path).mkdirs();
        }
        JSONArray files = downloadFile(file_url);
        NetReq n = new NetReq(Header);
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        StringBuilder sb = new StringBuilder();
        for(int i=0;i|]"," ");
            //Date date = file.getDate("create_time");
            // https://api.zsxq.com/v2/files/51588882112214/download_url
            String download_url = JSONObject.parseObject(n.get(String.format("https://api.zsxq.com/v2/files/%s/download_url",file_id)))
                    .getJSONObject("resp_data").getString("download_url");
            //在windows7及更高版本的系统中可以直接利用powershell自带的功能下载
            System.out.println("正在尝试下载文件:" + name);
            System.out.println(String.format("powershell (new-object Net.WebClient).DownloadFile('%s','%s')",download_url,dl_path + name));
            Runtime.getRuntime().exec(String.format("powershell (new-object Net.WebClient).DownloadFile('%s','%s')",download_url,dl_path + name));
            //Thread.sleep(100);
            sb.append(download_url).append('\n');
        }
        FileOutputStream fos = new FileOutputStream(new File("如果星球文件没有自动下载成功,请将此目录导入到迅雷等工具批量下载.txt"));
        fos.write(sb.toString().getBytes(StandardCharsets.UTF_8));
    }
    private JSONArray downloadFile(String url) throws Exception{
        String req_url = url;
        NetReq n = new NetReq(Header);
        JSONArray files = new JSONArray();
        while(true) {
            String result = n.get(req_url);
            JSONArray new_files = JSONObject.parseObject(result).getJSONObject("resp_data").getJSONArray("files");
            if (new_files == null || new_files.size() == 0) {
                return files;
            }
            Date last_date = new_files.getJSONObject(new_files.size() - 1).getJSONObject("file").getDate("create_time");
            addToJarr(files,new_files);
            SimpleDateFormat sdf_t = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
            String end_time = sdf_t.format(last_date) + ".000+0800";
            req_url = url + "&end_time=" + URLEncoder.encode(end_time, StandardCharsets.UTF_8);
        }
    }
    private void addToJarr(JSONArray add_to, JSONArray to_add){
        addToJarr(add_to,to_add,true);
    }
    private boolean is_wanted(JSONObject cur_obj,boolean limit){
        //没有限制添加,则直接返回true
        if(!limit) return true;
        //首先检查月份限制
        Date date = cur_obj.getDate("create_time");
        if(date==null) date = cur_obj.getJSONObject("file").getDate("create_time");
        Calendar c = Calendar.getInstance(); c.setTime(date);
        if(month>-1&&c.get(Calendar.MONTH)!=month) {
            //不在同一个月份,不能添加
            return false;
        }
        //接下来检查作者是不是在指定列表中
        boolean in_auth_list = false;
        JSONArray author_list = (JSONArray)config_map.get("accept_author_id");
        if(author_list!=null) {
            long author_id = 0;
            try {
                JSONObject content;
                String type = cur_obj.getString("type");
                if(type==null) {type=cur_obj.getJSONObject("topic").getString("type"); cur_obj=cur_obj.getJSONObject("topic");}
                if (type.equals("q&a")) content = cur_obj.getJSONObject("answer");
                else {
                    content = cur_obj.getJSONObject(type);
                    if(type.equals("topic")) content = content.getJSONObject("talk");
                }
                //System.out.println(content.toString());
                author_id = content.getJSONObject("owner").getLongValue("user_id");
                for (int i = 0; i max_title_length) {
                    title = title.substring(0, max_title_length);
                }
                sb.append(String.format("\n\n### %d. %s
%s\n\n",++topic_count,title,time));
                if(debug){
                    //调试模式下输出主题的id,方便创建排除名单
                    long topic_id = 0;
                    try {
                        topic_id = cur_topic.getLongValue("topic_id");
                    } catch (NullPointerException npe) {
                        System.err.println("警告:未匹配到主题的id,请增加判断规则");
                        System.out.println(cur_topic.toString());
                    }
                    sb.append("id: ").append(topic_id).append('\n');
                }
                sb.append(String.format("%s
",text)).append('\n');
                //如果附带了文件就追加文件信息,且需要文件(需要配合下载文件功能使用)
                if((boolean)config_map.get("need_file")){
                    JSONArray files = topic_obj.getJSONArray("files");
                    if(files!=null){
                        for(int j=0;jmax_title_length) {
                            title = title.substring(0, max_title_length);
                        }
                    }
                    sb.append(String.format("\n\n### %d. %s
%s \n\n",++q_a_count,title,time)).append('\n');
                    if(debug){
                        long topic_id = 0;
                        try {
                            topic_id = cur_topic.getLongValue("topic_id");
                        } catch (NullPointerException npe) {
                            System.err.println("警告:未匹配到主题的id,请增加判断规则");
                            System.out.println(cur_topic.toString());
                        }
                        sb.append("id: ").append(topic_id).append('\n');
                    }
                    //提问部分
                    String q_text = q.getString("text");
                    sb.append(String.format("> %s\n", q_text)).append('\n');
                    sb.append(get_imgs(q));
                    if(cur_topic.getBoolean("answered")){
                        //回答部分
                        String a_text = a.getString("text");
                        sb.append(String.format("\n
[color=]%s
\n", a_text));
                        sb.append(get_imgs(a));
                    }else{
                        sb.append(String.format("\n
[color=]%s
\n", "暂无回答"));
                    }
                }catch (Exception e){
                    e.printStackTrace();
                    System.out.println(cur_topic);
                }
            }
        }
        return sb.toString();
    }
}
您需要登录后才可以回帖 登录 | 立即注册

返回顶部