我最近一直在尝试手动执行以下操作,我想知道是否有一种快速的方法可以自动执行此操作。我唯一的经验是在Ubuntu的终端中使用python / python3,这就是为什么我希望在python中而不是其他地方使用它。
某些背景:网站my.comics.org是漫画书的数据库,其中给定的期刊的URL格式为https://my.comics.org/issue/#
,其中#
是一个数字。如果已登录一个帐户,则有一个“添加”按钮,可将问题添加到所选列表中。我正在尝试整理一个脚本,该脚本将循环遍历与数字范围相对应的URL,并将每个问题添加到选定列表中。选择列表保存在浏览器中,因此无需指定,因此只需单击按钮即可。检查“添加”按钮,html
<input type="submit" name="confirm_selection" value="Add">`
我希望该信息足以告诉脚本单击哪个按钮。
我知道我可以使用webbrowser模块打开网页,但是我不知道如何打开URL,单击“添加”按钮,关闭标签,然后在给定范围内重复。
只是做实验,我在python命令行中尝试了类似的方法
import webbrowser
for i in range(1,5):
webbrowser.open('https://my.comics.org/issue/'+str(i))
这打开了很多标签,但是我遇到了类似的错误
Unable to open /var/lib/snapd/desktop/dconf/profile/user: Permission denied
我也不想同时打开所有选项卡,因为我想在1000个问题范围内运行脚本。有没有简单的方法可以做到这一点?谢谢。
答案 0 :(得分:1)
有一些空闲时间,所以我在my.comics.org上注册了一个帐户。
我不会为此使用super.componentDidUpdate
模块。相反,我将使用webbrowser
模块。使用requests
,您可以向网站发出HTTP GET和POST请求(以及其他一些请求)。这个想法是,您创建一个请求有效负载并将其提交到所需的URL,以便您或多或少地模仿您将在浏览器中执行的“操作”。最难的部分是使您的请求格式正确,并知道要放入哪些内容,以便接收服务器将其接受。
这是我想出的代码(请注意,我在多个地方使用f字符串,这是Python 3.6的功能。如果没有f字符串,则可以进行简单的旧字符串格式化) :
requests
一些注意事项:
第一步是创建请求会话,就像您访问网站时浏览器为您创建会话一样。我们接下来要做的就是登录我们的帐户。为此,我们需要一个“用户名”(电子邮件)和密码。我们还需要一个称为CSRF令牌的东西,它是服务器发送给您的一次性Cookie,用于唯一标识您的会话。我们的设置方法是创建一个字典,该字典将“用户名”映射到您的电子邮件,将“密码”映射到您的密码等。我们几乎准备提交第一个POST请求,但是您还必须提供标题到服务器,以哪种方式描述您的客户端以及您来自哪里(服务器通常也希望看到此信息以确保您的请求是真实的)。
在第一个POST请求之后,我们应该立即登录(请注意,与webbrowser模块不同,这些都不会打开任何选项卡或浏览器实例。所有操作都在后台进行)。登录后,我们可以遍历我们有兴趣添加到集合中的问题。
注意,对于我的collection_id,我选择了值“ 27402”。您可能必须更改此值,因为这是我的收藏的ID(我为此项目创建了一个“ python收藏”)。我找出要添加的集合ID的方法是查看HTML:
def main():
import requests
login_url = "https://my.comics.org/accounts/login/"
client = requests.session()
# First, get the CSRF token.
client.get(login_url)
csrf_token = client.cookies["csrftoken"]
email = "YOUR EMAIL GOES HERE"
password = "YOUR PASSWORD GOES HERE"
credentials = {
"username": email,
"password": password,
"csrfmiddlewaretoken": csrf_token,
"next": "/"
}
headers = {
"User-Agent": "User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36",
"Referer": login_url,
"Connection": "keep-alive",
"Host": "my.comics.org",
"Origin": "https://my.comics.org"
}
request = client.post(login_url, data=credentials, headers=headers)
# We should be logged in now.
# Here is where we can start adding the issues to our desired collection(s).
issue_numbers = [41485, 41486, 41487]
collection_id = "27402"
number_of_issues = len(issue_numbers)
for issue_index, issue_number in enumerate(issue_numbers):
issue_url = f"https://my.comics.org/issue/{issue_number}/add_to_collection/"
# Get the CSRF token again.
client.get(issue_url)
csrf_token = client.cookies["csrftoken"]
data = {
"csrfmiddlewaretoken": csrf_token,
"confirm_selection": "Add",
"collection_id": collection_id,
}
headers["Referer"] = issue_url
print(f"({issue_index+1}/{number_of_issues}) Adding issue# {issue_number} to collection# {collection_id}...")
request = client.post(issue_url, data=data, headers=headers)
print("All done!")
return 0
if __name__ == "__main__":
import sys
sys.exit(main())
注意,我的python集合的“值”。这就是我们可以从“添加”按钮下的下拉窗口中选择的集合的ID。
我们将各个问题编号添加到集合中的方法是迭代/循环遍历我们的问题编号列表(在这种情况下,我只是随机选择了三个)。对于列表中的每个发行号,我们需要获取一个新的CSRF令牌,并更改标题词典中的“ Referer”字段(以反映我们所来自的新位置)。然后,循环中的POST请求实际上就是将当前问题添加到指定集合中的请求。
而且,以防万一您感到好奇,这是我在终端机上获得的输出:
<form method="POST" action="/issue/41485/add_to_collection/">
<input type='hidden' name='csrfmiddlewaretoken' value='REDACTED, NORMALLY A BUNCH OF RANDOM CHARACTERS' />
<div>
<input type="submit" name="confirm_selection" value="Add">
this issue to your
<select name="collection_id">
<option value="27400" >Default have collection
<option value="27401" >Default want collection
<option value="27402" >python collection
</select>
</div>
</form>