代码如下:
import socket, ssl HOST = 'www.bilibili.com' sock = socket.socket() sock = ssl.wrap_socket(sock) sock.connect((HOST, 443)) request = f'GET / HTTP/1.1\r\nHOST: {HOST}\r\nConnection: close\r\n\r\n' sock.send(request.encode()) SIZE = 8192 buffer = [] while True: print(sock) data = sock.recv(SIZE) if not data: break buffer.append(data) data = b''.join(buffer) sock.close() data = data.split(b'\r\n\r\n', 1)[1] print(data.decode())
GET 请求 B 站首页,返回的数据有时能正常解码为 UTF8,有时又会解码到一半报错提示无法解码,报错时我试着先把字节存到一个文件,然后按 UTF8 只解码前面的部分,可以正常解码。 代码跑多几遍就会出现(手动跑个 5、6 遍,应该跟反爬虫没关联吧),访问豆瓣 TOP250 电影( https://movie.douban.com/top250 )页面也会出现这个情况,豆瓣触发次数得跑多几遍,而且是固定位置报错,这个感觉很诡异,固定位置也不可能是传输数据丢了吧?这个问题困扰了我好几天了,望各位不吝赐教。
![]() | 1 ysc3839 2019-09-14 19:02:43 +08:00 via Android 发一下有问题的数据看看? |
![]() | 2 Danpier OP |
![]() | /td> | 3 ipwx 2019-09-14 19:23:42 +08:00 via Android try: data.decode(errors='ignore') |
6 aquariumm 2019-09-14 19:34:37 +08:00 via Android 我猜是 brotli ? |
![]() | 7 Danpier OP @ysc3839 V2EX 链接: https://pan.baidu.com/s/17Abee6spBYuvS7r5EG4mXw 提取码: 8ku1 贴下 header 部分: HTTP/1.1 200 OK Date: Sat, 14 Sep 2019 11:18:13 GMT Content-Type: text/html; charset= Transfer-Encoding: chunked Connection: close gear: 1 vikingrCache: 60000 Vikingr-Cache-TTL: 4376 IDC: shjd Vary: Origin,Accept-Encoding Expires: Sat, 14 Sep 2019 11:18:43 GMT Cache-Control: max-age=30 X-Cache-Webcdn: BYPASS from hw-gz3-webcdn-07 报错位置在 34556,试了解码前 30000 没问题。 |
![]() | 9 gamexg 2019-09-14 21:01:56 +08:00 协议设置为 http 1.0 版本试试, Transfer-Encoding 之类功能都可能出问题 |
![]() | 10 wwqgtxx 2019-09-14 21:55:08 +08:00 via iPhone 默默地问一下为啥不用 requests 或者 aiohttp,或者看看他们的源代码是怎么处理这种编码问题的 |
![]() | 12 autogen 2019-09-15 00:01:22 +08:00 gzip 了吗? |
![]() | 13 ysc3839 2019-09-15 20:23:15 +08:00 @Danpier 看了数据,是 Transfer-Encoding: chunked 的问题。 https://imququ.com/post/transfer-encoding-header-in-http.html 另外,如无特殊需求,不建议自己实现 HTTP 客户端。 |
![]() | 14 Danpier OP |
15 lolizeppelin 2019-09-16 09:00:48 +08:00 via Android 你的问题 应该去看 rfc 标准 |
![]() | 16 gamexg 2019-09-16 10:07:53 +08:00 @Danpier #14 协议上面没要求 Connection: close 后就不能 Transfer-Encoding: chunked,所以服务器可以这么做。 另外如果代码如主题所写,那么你并未移除每个块开头的标记信息,这个需要手工移除。 参考文档: https://imququ.com/post/transfer-encoding-header-in-http.html |