python - Python 3 写入 json 文件时出现双反斜杠问题
问题描述
我使用urllib.request
and regex
forhtml parse
但是当我在json
文件中写入时,文本中有双反斜杠。如何替换一个反斜杠?我查看了许多解决方案,但没有一个有效。
headers = {}
headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'
req = Request('https://www.manga-tr.com/manga-list.html', headers=headers)
response = urlopen(req).read()
a = re.findall(r'<b><a[^>]* href="([^"]*)"',str(response))
sub_req = Request('https://www.manga-tr.com/'+a[3], headers=headers)
sub_response = urlopen(sub_req).read()
manga = {}
manga['manga'] = []
manga_subject = re.findall(r'<h3>Tan.xc4.xb1t.xc4.xb1m<.h3>[^<]*.n.t([^<]*).t',str(sub_response))
manga['manga'].append({'msubject': manga_subject })
with io.open('allmanga.json', 'w', encoding='utf-8-sig') as outfile:
outfile.write(json.dumps(manga, indent=4))
这是我的 json 文件
{
"manga": [
{
"msubject": [
" Minami Ria 16 ya\\xc5\\x9f\\xc4\\xb1ndad\\xc4\\xb1r. \\xc4\\xb0lk erkek arkada\\xc5\\x9f\\xc4\\xb1 sakatani jirou(16) ile yakla\\xc5\\x9f\\xc4\\xb1k 6 ayd\\xc4\\xb1r beraberdir. Herkes taraf\\xc4\\xb1ndan \\xc3\\xa7ifte kumru olarak g\\xc3\\xb6r\\xc3\\xbclmelerine ra\\xc4\\x9fmen ili\\xc5\\x9fkilerinde %1\\'lik bir eksiklik vard\\xc4\\xb1r. Bu eksikli\\xc4\\x9fi tamamlayabilecekler mi?"
}
]
}
解决方案
为什么会这样?
错误是 whenstr
用于将bytes
对象转换为str
. 这不会以所需的方式进行转换。
a = re.findall(r'<b><a[^>]* href="([^"]*)"',str(response))
# ^^^
例如,如果响应是单词“Tanıtım”,那么它会在 UTF-8 中表示为b'Tan\xc4\xb1t\xc4\xb1m'
. 如果你然后使用str
它,你会得到:
In [1]: response = b'Tan\xc4\xb1t\xc4\xb1m'
In [2]: str(response)
Out[2]: "b'Tan\\xc4\\xb1t\\xc4\\xb1m'"
如果将其转换为 JSON,您将看到双反斜杠(实际上只是普通的反斜杠,编码为 JSON)。
In [3]: import json
In [4]: print(json.dumps(str(response)))
"b'Tan\\xc4\\xb1t\\xc4\\xb1m'"
bytes
将对象转换回 a的正确方法str
是使用decode
具有适当编码的方法:
In [5]: response.decode('UTF-8')
Out[5]: 'Tanıtım'
请注意,不幸的是,响应不是有效的 UTF-8。网站运营商似乎在提供损坏的数据。
快速解决
替换每次调用str(response)
withresponse.decode('UTF-8', 'replace')
并更新正则表达式以匹配。
a = re.findall(
# "r" prefix to string is unnecessary
'<b><a[^>]* href="([^"]*)"',
response.decode('UTF-8', 'replace'))
sub_req = Request('https://www.manga-tr.com/'+a[3],
headers=headers)
sub_response = urlopen(sub_req).read()
manga = {}
manga['manga'] = []
manga_subject = re.findall(
# "r" prefix to string is unnecessary
'<h3>Tanıtım</h3>([^<]*)',
sub_response.decode('UTF-8', 'replace'))
manga['manga'].append({'msubject': manga_subject })
# io.open is the same as open
with open('allmanga.json', 'w', encoding='utf-8-sig') as fp:
# json.dumps is unnecessary
json.dump(manga, fp, indent=4)
更好的修复
使用“请求”
Requests库比使用urlopen
. 您必须安装它(使用 pip、apt、dnf 等,无论您使用什么),它不随 Python 提供。它看起来像这样:
response = requests.get(
'https://www.manga-tr.com/manga-list.html')
然后response.text
包含解码后的字符串,不需要自己解码。更轻松!
使用 BeautifulSoup
Beautiful Soup库可以搜索 HTML 文档,比正则表达式更可靠,更易于使用。它也需要安装。例如,您可以像这样使用它来查找漫画页面中的所有摘要:
soup = BeautifulSoup(response.text, 'html.parser')
subject = soup.find('h3', text='Tanıtım').next_sibling.string
概括
这是一个Gist,其中包含一个更完整的刮板外观示例。
请记住,抓取网站可能有点困难,因为您可能会抓取 100 个页面,然后突然发现您的抓取器有问题,或者您访问网站的力度太大,或者某些内容崩溃并失败,您需要重来。因此,良好的抓取通常涉及速率限制、保存进度和缓存响应,以及(理想情况下)解析 robots.txt。
但Requests + BeautifulSoup至少能让你入门。再次,请参阅要点。
推荐阅读
- python - 在python中多次分配给变量的地图对象上使用列表函数
- django - 用于多个域和同一站点的 Django 站点地图
- time-complexity - 分布式网络算法的时间复杂度
- javascript - 将 BrowserWindow 重构为单独的文件后捕获的异常
- java - spring data JPA repository.save方法自动保存所有实体?
- git - Git 合并来自另一个分支的部分更改
- javascript - 使用 React.js 通过 ChartJS 活动元素中的 onClick 传递未知值
- android - 错误:活动类 {com.example.cupcake/com.example.cupcake.MainActivity} 不存在
- android - 断言在 JetPack Compose 测试中是否抛出异常
- d - 如何使用 dub 构建 DAllegro 项目?