TypeError:在尝试发送 http 请求时需要一个类似字节的对象,而不是“str”

Posted

技术标签:

【中文标题】TypeError:在尝试发送 http 请求时需要一个类似字节的对象,而不是“str”【英文标题】:TypeError: a bytes-like object is required, not 'str' while trying to send a http request 【发布时间】:2022-01-04 03:02:16 【问题描述】:

我正在尝试向用户输入的站点发送http响应,然后打印响应,代码如下:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
url = input("Enter a web address and press Enter: ")
s.connect((url, 80))
# s.send("GET / HTTP/1.0\r\n\r\n")
s.send(b"HTTP/1.1 200 OK\nContent-Type: text/html\r\n\r\n")
print(s.recv(1028))
s.close()

但是,我收到了上述错误。不太清楚为什么。我也尝试连接发送请求,但说我不能有类似字节的对象。任何帮助将不胜感激。

编辑:我尝试对路人发送的链接中的文本进行编码,但是我没有收到 html 响应,我收到了一个错误的请求:

b'HTTP/1.0 400 Bad Request\r\nContent-Type: text/html; charset=UTF-8\r\nReferrer-Policy: no-referrer\r\nContent-Length: 1555\r\nDate: Thu, 25 Nov 2021 22:48:41 GMT\r\n\r\n<!DOCTYPE html>\n<html lang=en>\n  <meta charset=utf-8>\n  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">\n  <title>Error 400 (Bad Request)!!1</title>\n  <style>\n    *margin:0;padding:0html,codefont:15px/22px arial,sans-serifhtmlbackground:#fff;color:#222;padding:15pxbodymargin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px* > bodybackground:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205pxpmargin:11px 0 22px;overflow:hiddeninscolor:#777;text-decoration:nonea imgborder:0@media screen and (max-width:772px)bodybackground:none;margin-top:0;max-width:none;padding-right:0#logobackground:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px@media only screen and (min-resolution:192dpi)#logobackground:url(/'

【问题讨论】:

这能回答你的问题吗? How do I encode a string to bytes in the send method of a socket connection in one line? 不是真的,我没有得到回复,html中的网站布局 您不会向网站发送回复。您发送请求,站点将发送响应作为回报。您应该发送s.send( b'GET / HTTP/1.0\r\n\r\n')。更好的是,使用出色的 requests 模块隐藏所有这些并让您专注于问题。 【参考方案1】:

您正在向用户询问作为字符串的 URL:

url = input("Enter a web address and press Enter: ")

然后你将该字符串传递给socket.send:

s.send("GET / HTTP/1.0\r\n\r\n")

但是,正如错误所说,socket.send 需要一个类似字节的对象。要从字符串中获取它,可以调用它的 encode 方法:

s.send("GET / HTTP/1.0\r\n\r\n".encode("utf-8"))

或从中创建一个bytes 对象并将其传递给socket.send

s.send(bytes("GET / HTTP/1.0\r\n\r\n"))

或者在字符串前面加上b

s.send(b"GET / HTTP/1.0\r\n\r\n")

【讨论】:

【参考方案2】:

您必须使用套接字来执行此操作吗?为什么不使用urllib.request

import urllib.request

url = input("Enter a web address and press Enter: ")

with urllib.request.urlopen(url) as f:
    print(f.read())

我正在运行它以点击https://www.example.com

Enter a web address and press Enter: https://www.example.com
b'<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta charset="utf-8" />\n    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />\n    <meta name="viewport" content="width=device-width, initial-scale=1" />\n    <style type="text/css">\n    body \n        background-color: #f0f0f2;\n        margin: 0;\n        padding: 0;\n        font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;\n        \n    \n    div \n        width: 600px;\n        margin: 5em auto;\n        padding: 2em;\n        background-color: #fdfdff;\n        border-radius: 0.5em;\n        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);\n    \n    a:link, a:visited \n        color: #38488f;\n        text-decoration: none;\n    \n    @media (max-width: 700px) \n        div \n            margin: 0 auto;\n            width: auto;\n        \n    \n    </style>    \n</head>\n\n<body>\n<div>\n    <h1>Example Domain</h1>\n    <p>This domain is for use in illustrative examples in documents. You may use this\n    domain in literature without prior coordination or asking for permission.</p>\n    <p><a href="https://www.iana.org/domains/example">More information...</a></p>\n</div>\n</body>\n</html>\n'

以下是使用socket 的方法:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
url = input("Enter a web address and press Enter: ")
s.connect((url, 80))
request = f"GET / HTTP/1.1\r\nHost:url\r\n\r\n"
s.send(request.encode())
print(s.recv(4096))
s.close()

我修改了这个程序:https://www.geeks3d.com/hacklab/20190110/python-3-simple-http-request-with-the-socket-module/

如果您需要它一直阅读到 EOF,请使用此模式:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
url = input("Enter a web address and press Enter: ")
s.connect((url, 80))
request = f"GET / HTTP/1.1\r\nHost:url\r\n\r\n"
s.send(request.encode())

response = ""

while True:
    chunk = s.recv(1024)
    if len(chunk) == 0:
        break
    response += str(chunk)

print(response)

【讨论】:

是的,我正在尝试在 python 中自学套接字和网络。尝试使用任何外部软件包。 urllib.request 不是外部的,它是 Python 的核心,就像 socket 一样。但我会更新一个有效的socket 示例。 为了读取到文件末尾,我们不需要解码直到 end= ' ' 吗?另外,为什么我们在编码时没有显式解码? 不知道,这似乎对我有用。我不使用 socket 发出 HTTP 请求。我使用requestsurllib.request

以上是关于TypeError:在尝试发送 http 请求时需要一个类似字节的对象,而不是“str”的主要内容,如果未能解决你的问题,请参考以下文章

TypeError:无法读取未定义的nodejs请求http的属性'0'

错误:TypeError:无法调用未定义的方法“替换”[重复]

Uncaught TypeError: $(...).value is not a function 尝试通过 JQuery 发送值时

postman 基本用法

Angular在发送之前获取原始http请求

在 Ruby 中发送 HTTP/2 POST 请求