返回文章列表文章索引阅读全文
STARBLOG / 阅读手记
爬虫

A Mysterious Crawler Bug Actually Made Me Give Up Python!? The Reason Behind It Is Heartbreaking~

Behind every successful programmer, there may stand countless bald men—providing them with various development tools & code libraries, of course including... all kinds of mysterious bugs... The Beginning of the Mystery Recently, while working on a crawler project with Python, I ran into a very strange problem, and it doesn't even trigger every time—truly baffling... The error message is as follows: UnicodeEncodeError: 'latin-1' codec can't encode character '\u2026' in pos

曦远 (DealiAxy)约 11 分钟
目录4 个章节

Behind every successful programmer, there may stand countless bald men—providing them with various development tools & code libraries, of course including... all kinds of mysterious bugs...

The Beginning of the Mystery

Recently, while working on a crawler project with Python, I ran into a very strange problem, and it doesn't even trigger every time—truly baffling...

The error message is as follows:

UnicodeEncodeError: 'latin-1' codec can't encode character '\u2026' in position 512: ordinal not in range(256)

I took the error message to a search engine and looked it up. The Chinese community said it was because there was Chinese data in the request body or headers,

and the solution was: first encode it as UTF-8, then decode it with latin-1 encoding.

But there was no Chinese in my request data!

Thus began a hair-loss-inducing journey of hunting down the bug

Looking at the Code

(Long and tedious—don't bother, suggest skipping to what follows)

First, let's look at the format of the data I submitted~

This is related to authentication (too long, so only a snippet)

"spider9": {
  "Authorization": "Basic Z2VjZW50ZXJfYWR",
  "Blade-Auth": "bearer eyJhbGciOiJIUzI1NiIsI",
  "cookie": "oauth=eyJhY2Nlc3NfdG"
}

Here's the header-related code

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0',
    'Accept': 'application/json, text/plain, */*',
    'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
    'Accept-Encoding': 'gzip, deflate', 'Content-Type': 'application/json;charset=utf-8',
    'Authorization': config['spider9']['Authorization'],
    'Blade-Auth': config['spider9']['Blade-Auth'].encode('utf-8').decode('latin1'),
    'Content-Length': '60', 'Connection': 'keep-alive',
    'Cookie': config['spider9']['cookie'],
    'Pragma': 'no-cache', 'Cache-Control': 'no-cache',
}

Here's the requests request code:

response = requests.post(
    url, headers=headers, verify=False,
    json={
        'cityCode': '1234',
        'createTimeFrom': None,
        'createTimeTo': None
    }
)

Just looking at this code, there shouldn't be any problem at all. In fact, my other crawlers are written the same way and have been running stably for over a year. It's just this newly written crawler that doesn't work... Sometimes code problems are just this mysterious...

As mentioned earlier, I found netizens suggesting the encode-then-decode method, so I tried adding it to the three fields Authorization, Blade-Auth, and Cookie in the headers:

'Authorization': config['spider9']['Authorization'].encode('utf-8').decode('latin1')

That way it no longer threw this UnicodeEncodeError, but the backend service directly reported an error saying I wasn't logged in...

So what kind of problem is this then?

I continued searching on Stack Overflow. A Russian netizen said they also ran into this problem, and there was a reply below suggesting trying to set an environment variable. OK, so I followed along and tried:

export PYTHONUTF8=1

Then I printed the system encoding and locale in Python:

import sys
import locale

print(sys.getfilesystemencoding())
print(locale.getpreferredencoding())

Output

utf-8
UTF-8

Oh wow~ Tried running it again... still didn't work. I'm speechless. So it wasn't this problem at all.

Alright, I surrender. I don't want to keep grinding away at it. Where I fall, there I lie down

So what was the problem? To this day it remains an unsolved mystery...

Aftermath

So tired. Switched to writing crawlers in C#, giving up Python...

What happened to “Life is short, I use Python”? How did it become such a hassle TAT...

(PS: I previously built a crawler platform that can schedule crawler programs implemented in different languages, providing a unified configuration center and a unified data persistence interface~ So it doesn't make much difference which language each crawler is written in)

I'm writing this article as a record, hoping that someday in the future this problem can be solved~ (A beautiful wish)

References

_EOF_

A Mysterious Crawler Bug Actually Made Me Give Up Python!? The Reason Behind It Is Heartbreaking~

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

Selenium爬虫实战:截取网页上的图片

前言 同样是为了刷课,没想到工作后依然和大学一样逃脱不了需要刷网课的命运…… 正文 直接说干货了,截取图片,需要截取的图片是什么图片大家都懂(说的就是你,验证码),其他图片的话不需要截取,直接拿到地址下载就行,验证码不行,同样的地址再访问一次内容就变了。 我不知道为啥selenium不能直接把特定img元素的图片拿出来,太反人类了。 根据我找到的资料,主要有两种思路,一种是模拟鼠标操作,在验证码上

2022-05-27 · 爬虫 · 约 1 分钟

Selenium爬虫实践:ajax请求抓包、浏览器退出

前言 最近在搞公司内部系统,累的一批,需要从另一个内部系统导出数据存到数据库做分析,有大量的数据采集工作,又没办法去直接拿到那个系统的接口,太难了,只能爬虫,但是cookie还经常失效,为了不每次登录失效就来找我重新注入Cookie,我写了一个手机版的网页,用来控制后台的selenium自动登录,截取token和cookie。 ajax请求抓包方案 搜索资料的过程真的痛苦,不过还好这时间没有白花,

2022-05-27 · 爬虫 · 约 1 分钟

爬虫笔记:代理池和线程池

前言 爬虫和反爬虫是一对矛和盾,反爬虫很常见的一个方法就是封IP,一个IP短时间内频繁访问,可以做限流或者是加入黑名单,我之前的后台开发相关博客也有涉及这一块。 不过今天说的是爬虫,所以应对的方法就是用代理池,每次请求都用不同的IP就行,再加上UA模拟,完全是正常用户的行为,可以避开限流和黑名单反爬。 然后爬虫是一种IO密集型程序,如果全程单线程执行那会很慢,因此可以用多线程来提高数据采集效率,不

2022-02-12 · 爬虫 · 约 1 分钟

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…