Python Web抓取CSRF令牌问题

Python Web抓取CSRF令牌问题,python,web-scraping,beautifulsoup,urllib,mechanicalsoup,Python,Web Scraping,Beautifulsoup,Urllib,Mechanicalsoup,我正在使用MechanicalSoup通过Python3.6登录到一个网站,我对CSRF令牌有问题 每次我请求返回html时,我都会读到“无效的CSRF令牌:禁止”。在登录页面上搜索html时,与看起来像令牌的元素id最匹配的是“authenticity_token”,它似乎已经用令牌填充 我能够使用“re”模块提取令牌,并使用上面提到的id重新提交给元素,但运气不好。注意,我必须按id查找元素,因为没有为它提供名称(这就是为什么我的Robobrowser方法不起作用) 这是我认为与CSRF相对

我正在使用MechanicalSoup通过Python3.6登录到一个网站,我对CSRF令牌有问题

每次我请求返回html时,我都会读到“无效的CSRF令牌:禁止”。在登录页面上搜索html时,与看起来像令牌的元素id最匹配的是“authenticity_token”,它似乎已经用令牌填充

我能够使用“re”模块提取令牌,并使用上面提到的id重新提交给元素,但运气不好。注意,我必须按id查找元素,因为没有为它提供名称(这就是为什么我的Robobrowser方法不起作用)

这是我认为与CSRF相对应的元素:

<input id="authenticity_token" type="hidden" value="b+csp/9zR/a1yfuPPIYJSiR0v8jJUTaJaGqJmJPmLmivSn4GtLgvek0nyPvcJ0aOgeo0coHpl94MuH/r1OK5UA==">

我认为这里的问题是
元素必须具有
name
属性才能通过POST或GET提交。由于您的令牌位于
名称
-less
元素中,因此MechanicalSoup不会对其进行处理,因为浏览器会这样做

从:

每个成功的控件都将其控件名与其当前值配对,作为提交表单数据集的一部分。成功的控件必须在表单元素中定义,并且必须具有控件名称

控件的“控件名”由其name属性提供

也许有一些JavaScript正在处理CSRF令牌

有关类似的讨论,请参见


关于对的使用,类
StatefulBrowser
Form
将简化脚本。例如,如果您只需打开页面并输入用户名和密码:

导入机械组
#这些值由用户填写
url=“”
username=“”
password=“”
#打开页面
browser=mechanicalsoup.StatefulBrowser(在_404上提升_=True)
浏览器打开(url)
#填写表单值
表单=浏览器。选择表单('form[id=loginForm]”)
表单['username']=用户名
表单['password']=密码
#提交表单并打印生成的页面文本
响应=浏览器。提交所选内容()
打印(response.text)

从外观上看,regex是错误的-您是否尝试过查看您的
令牌
并检查其是否正确。另外-该库不支持从表单中获取值而不是使用该方法吗?@JonClements正则表达式确实有效,这不是问题所在,它可以从引号中提取值。我不能使用robobrowser,因为它得到一个表单,然后允许您按元素名称输入值(这一个没有名称,并且是omited)。看起来它可以将所有内容提取到下一个可以找到的引号中,而不是最直接的引号中…我在几次运行期间检查了该值,结果正确。我想我遇到的问题是,我甚至不确定我是否提交了正确的元素,或者这是否是正确的方法,只是快速浏览了一下库(实际上是2分钟的快速阅读)-您不应该在表单元素上使用
mechanicalsoup.Form
创建表单实例,然后填充并提交吗?这看起来还将考虑您未覆盖的字段,例如隐藏字段,并将它们与您的请求一起发送。。。但不确定-还没有尝试过。。。但看起来这就是它应该被使用的方式。(如果是这样,你甚至不必再担心这个领域)
import mechanicalsoup
import re

def return_token(str1):
    match1 = "authenticity_token"
    match2 = ".*value\=\"(.*)\".*"
    for x in range(len(str1)):
        line = str1[x]
        if re.findall(match1,line):
            token = re.findall(match2,line)[0]
            return token

url1 = ""
username = ""
password = ""

browser = mechanicalsoup.Browser()
page = browser.get(url1)
str0 = page.text
token = return_token(str0.split('\n'))
#print(str0)
form = page.soup.find("form",{"id":"loginForm"})

form.find('input', {'name': 'username'})['value'] = username
form.find('input', {'name': 'password'})['value'] = password
form.find('input', {'id': 'authenticity_token'})['value'] = str(token)

response = browser.submit(form, page.url)
print(response.text)