在使用Python爬虫时需要设置请求标头(headers)来完全模拟一个浏览器进程访问网页,通常是设定一个字典格式的headers,内容是user-agent,比如:
headers={'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'}
但在调试某些网站时的headers往往需要设置多行内容如cookie、referer、host等信息。首先你要在浏览器F12界面里复制请求标头信息,然后粘贴在Python代码里再逐行修改成字典格式,行数多的情况下还真麻烦。不如自己做一个自动转换headers为Python的字典格式的专用函数。
以前我对input()的印象是一次只能输入一行字符串,但经过实践,Python的input()可以做到接收多行文字信息。举个例子:
a=input()
就在你粘贴多行文字并且按回车键之后,多行文字信息被送进了缓冲区,这个a变量会先接收第一行字符串。
接下来,每次访问input()时赋值a=input(),这时的a变成了第二行;
再来一次a=input(),a值变成了第三行,如此类推。
我们可以对每次赋值给a之后做一个列表,将多行的字符串转为列表,列表的每一个元素对应一行字符串。那什么时候让a值知道输入的缓冲区已清空呢?我的想法是用while循环判断a的长度,只要是空字符串,那就结束while循环。
最后将列表转换为Python的字典格式。测试代码如下:
def my_header():
l=[]
print('请按Ctrl+V粘贴多行请求标头:')
a=input()
while a:
l.append(a)
a=input() # 循环读取input()内容,直到遇到空行为止
h={}
for i in l:
aa=i.split(':',1) # 分割第一个冒号
h.update({aa[0]:aa[1].lstrip()})
return h
if __name__ == "__main__":
headers=my_header()
print('多行请求标头已转换为字典格式:\nheaders={')
for i in headers.keys():
print (f"'{i}': '{headers[i]}',")
print('}')
自编函数my_header()里分两个步骤:先接收多行字符串,然后转化为字典格式。
这个函数可以精简一下,取消对列表的赋值,直接拆解字符串转换为字典。
我写这段代码没有引入其他库,仅仅用Python自带的函数简单地实现多行输入,
def my_header():
h={}
a=input('请按Ctrl+V粘贴多行请求标头:')
while a:
aa=a.split(':',1) # 只分割第一个冒号
h.update({aa[0]:aa[1].lstrip()})
a=input() # 循环读取input()内容,直到遇到空行为止
return h
if __name__ == "__main__":
headers=my_header()
print('多行请求标头已转换为字典格式:\nheaders={')
# 下面是输出headers内容的另一种写法:
for k,v in headers.items():
print (f"'{k}': '{v}',")
print('}')
运行代码,先按Ctrl+V粘贴请求标头的多行文字,按回车键,然后自动输出字典格式的headers。
bug提示:
本人编写的这个程序不能处理多行文字混杂空行的情况。在粘贴含有空行的多行字符串后,只能处理空行之前的字符串,空行之后的字符串仍留存在缓冲区,下次访问input()时将会接收到其他行的字符串。
要修复上述的bug,就需要使用sys库的sys.stdin.read()实现,请参考以下我的博文:
Python使用sys.stdin.read()多行输入状态下如何结束输入
2023年1月3日更新:完美修复bug
最近想起sys库的stdin用法,我使用dir语句查看一下stdin有哪些功能(输入:dir(stdin)),发现有一个与缓冲区相关的语句:_line_buffer,这个正是我要找的可以修复上述bug的关键。
在a=input() 输入多行文字之后,a被赋予第一行字符串,再输入stdin._line_buffer即可看到其他行的字符串,包括空行。
接下来代码就完善了:
from sys import stdin
def my_header():
h = {}
b = []
a = input('请按Ctrl+V粘贴多行请求标头:\n')
# 列表b储存多行输入的文字
b = [a] + stdin._line_buffer.split('\n')
# 清空输入缓冲区
stdin._line_buffer = ''
print (b)
for i in b:
if i != '':
aa = i.split(':',1) # 只分割第一个冒号
h.update({aa[0]:aa[1].lstrip()}) # lstrip()用于清除字符串左边的空格
return h
if __name__ == "__main__":
headers = my_header()
print('多行请求标头已转换为字典格式:\nheaders={')
for k,v in headers.items():
print (f"'{k}': '{v}',")
print('}')
运行结果截图: