使用Python-requests在JSF网站(SIGAA UnB)发起POST请求失败求助
问题描述
我想在SIGAA UnB网站实现“选择院系、年份、学历后点击搜索”对应的POST请求。我用火狐开发者工具查看了POST请求详情,复制了请求头和请求体,提取了ID和会话Cookie,还把HTML响应导出到文件,但每次尝试都只返回初始页面,就像POST请求没生效一样,求指出缺失的部分。
原代码如下:
from bs4 import BeautifulSoup as BS4 import requests page = requests.Session() # GET Method to search for Cookies and IDs answer = page.get("https://sigaa.unb.br/sigaa/public/turmas/listar.jsf?aba=p-ensino") my_cookie = answer.cookies j_id = BS4(answer.text, "html.parser").find(id="javax.faces.ViewState")["value"] post_header = { "Host": "sigaa.unb.br", "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/114.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "Accept-Language": "pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate, br", "Content-Type": "application/x-www-form-urlencoded", "Content-Length": "194", "Origin": "https://sigaa.unb.br", "Connection": "keep-alive", "Referer": "https://sigaa.unb.br/sigaa/public/turmas/listar.jsf?aba=p-ensino", "Cookie": str(my_cookie["JSESSIONID"]), "Upgrade-Insecure-Requests": "1", "Sec-Fetch-Dest": "document", "Sec-Fetch-Mode": "navigate", "Sec-Fetch-Site": "same-origin", "Sec-Fetch-User": "?1", } post_form = { "formTurma": "formTurma", "formTurma:inputNivel" : "G", "formTurma:inputDepto" : "673", "formTurma:inputAno" : "2023", "formTurma:inputPeriodo" : "1", "formTurma:j_id_jsp_1370969402_11" : "Buscar", "javax.faces.ViewState": str(j_id), } answer = page.post("https://sigaa.unb.br/sigaa/public/turmas/listar.jsf?aba=p-ensino", data=post_form, headers=post_header, cookies=my_cookie) profile_file = open("sigaa.html", "w") profile_file.write(answer.text)
问题排查与修复
以下是导致请求失效的核心问题和修复方案:
Cookie重复设置冲突:你已经用
requests.Session()管理会话,它会自动保存和发送Cookie,但你又手动在请求头加了Cookie字段,还在POST时传了cookies=my_cookie,这会导致服务器收到重复或错误的Cookie信息。直接删掉请求头里的Cookie字段,POST时也不用传cookies参数,让Session自动处理即可。硬编码Content-Length无效:
Content-Length是根据请求体实际长度自动计算的,手动硬编码的数值如果和实际请求体长度不匹配,服务器会拒绝处理请求。直接移除请求头里的Content-Length字段。动态按钮ID硬编码:
formTurma:j_id_jsp_1370969402_11是JSF动态生成的按钮name属性,每次会话可能变化,不能硬编码。应该从初始GET请求的页面里解析——用BeautifulSoup找到显示文本为“Buscar”的按钮,提取它的name值。冗余请求头可移除:
Host字段requests会自动设置,不需要手动添加,可从请求头中移除。
修改后的代码
from bs4 import BeautifulSoup as BS4 import requests page = requests.Session() # 获取初始页面、Cookie和必要参数 target_url = "https://sigaa.unb.br/sigaa/public/turmas/listar.jsf?aba=p-ensino" initial_response = page.get(target_url) soup = BS4(initial_response.text, "html.parser") # 提取ViewState view_state = soup.find(id="javax.faces.ViewState")["value"] # 提取搜索按钮的动态name属性 search_btn_name = soup.find("input", {"value": "Buscar"})["name"] # 构造精简后的请求头 post_headers = { "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/114.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "Accept-Language": "pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate, br", "Content-Type": "application/x-www-form-urlencoded", "Origin": "https://sigaa.unb.br", "Connection": "keep-alive", "Referer": target_url, "Upgrade-Insecure-Requests": "1", "Sec-Fetch-Dest": "document", "Sec-Fetch-Mode": "navigate", "Sec-Fetch-Site": "same-origin", "Sec-Fetch-User": "?1", } # 构造请求体,使用动态获取的按钮name post_data = { "formTurma": "formTurma", "formTurma:inputNivel": "G", "formTurma:inputDepto": "673", "formTurma:inputAno": "2023", "formTurma:inputPeriodo": "1", search_btn_name: "Buscar", "javax.faces.ViewState": view_state, } # 发送POST请求,Session自动管理Cookie final_response = page.post(target_url, data=post_data, headers=post_headers) # 保存响应内容 with open("sigaa.html", "w", encoding="utf-8") as output_file: output_file.write(final_response.text)
内容的提问来源于stack exchange,提问作者Raphides
相关产品推荐
相关产品推荐

