当前位置: 首页 > 面试题库 >

设置编解码器/在Elasticsearch中搜索Python中的unicode值

闻人哲茂
2023-03-14
问题内容

此问题可能是由于我对ELK,Python和Unicode不满意。

我有一个索引,其中包含经过logstash消化的日志,包括一个包含主机名的字段“ host_req”。使用Elasticsearch-
py,我将该主机名从记录中拉出,并使用它来搜索另一个索引。但是,如果主机名包含多字节字符,它将失败并显示UnicodeDecodeError。当我在命令行中使用“
curl -XGET”输入相同的查询时,它确实可以正常工作。unicode字符是带有小写字母(两个点)的小写字母“ a”。UTF-8值为C3
A4,而Unicode代码点似乎是00E4(语言是瑞典语)。

这些curl命令可以从命令行正常运行:

 curl -XGET 'http://localhost:9200/logstash-2015.01.30/logs/_search?pretty=1' -d ' { "query" : {"match" :{"req_host" : "www.utkl\u00E4dningskl\u00E4derna.se" }}}'
 curl -XGET 'http://localhost:9200/logstash-2015.01.30/logs/_search?pretty=1' -d ' { "query" : {"match" :{"req_host" : "www.utklädningskläderna.se" }}}'

他们找到并返回记录

(第二行显示了主机名在我从中提取的日志中的显示方式,在两个位置显示了带有小写字母的小写字母“ a”)

我编写了一个非常简短的Pythonhtml" target="_blank">脚本来显示问题:它使用硬连线查询,打印它们及其类型,然后尝试在搜索中使用它们。

 #!/usr/bin/python
 # -*- coding: utf-8 -*-

 import json
 import elasticsearch

 es = elasticsearch.Elasticsearch()

 if __name__=="__main__":
   #uq = u'{ "query": { "match": { "req_host": "www.utklädningskläderna.se" }}}'           # raw utf-8 characters. does not work
   #uq = u'{ "query": { "match": { "req_host": "www.utkl\u00E4dningskl\u00E4derna.se" }}}' # quoted unicode characters. does not work
   #uq = u'{ "query": { "match": { "req_host": "www.utkl\uC3A4dningskl\uC3A4derna.se" }}}' # quoted utf-8 characters. does not work
   uq = u'{ "query": { "match": { "req_host": "www.facebook.com" }}}'                     # non-unicode. works fine
   print "uq", type(uq), uq
   result = es.search(index="logstash-2015.01.30",doc_type="logs",timeout=1000,body=uq);
   if result["hits"]["total"] == 0:
     print "nothing found"
   else:
     print "found some"

如果我如图所示运行它,并使用“ facebook”查询,那就很好了-输出为:

$python testutf8b.py
uq <type 'unicode'> { "query": { "match": { "req_host": "www.facebook.com" }}}
found some

请注意,查询字符串’uq’是unicode。

但是,如果我使用其他三个字符串(包括Unicode字符),它就会炸毁。例如,在第二行中,我得到:

$python testutf8b.py
uq <type 'unicode'> { "query": { "match": { "req_host": "www.utklädningskläderna.se" }}}
Traceback (most recent call last):
   File "testutf8b.py", line 15, in <module>
    result = es.search(index="logstash-2015.01.30",doc_type="logs",timeout=1000,body=uq);
  File "build/bdist.linux-x86_64/egg/elasticsearch/client/utils.py", line 68, in _wrapped
  File "build/bdist.linux-x86_64/egg/elasticsearch/client/__init__.py", line 497, in search
  File "build/bdist.linux-x86_64/egg/elasticsearch/transport.py", line 307, in perform_request
  File "build/bdist.linux-x86_64/egg/elasticsearch/connection/http_urllib3.py", line 82, in perform_request
elasticsearch.exceptions.ConnectionError: ConnectionError('ascii' codec can't decode byte 0xc3 in position 45: ordinal not in range(128)) caused by: UnicodeDecodeError('ascii' codec can't decode byte 0xc3 in position 45: ordinal not in range(128))
$

再次注意,查询字符串是一个unicode字符串(是的,源代码行是带有\u00E4字符的字符串)。

我真的很想解决这个问题。我尝试了uq = uq.encode("utf=8")和的各种组合uq = uq.decode("utf=8"),但似乎无济于事。我开始怀疑elasticsearch-py图书馆是否存在问题。

谢谢!

pt

PS:这是在Centos 7下,使用ES 1.5.0。使用logstash-1.4.2将日志摘要消化到稍旧版本的ES中


问题答案:

基本上,您不需要body作为字符串传递。使用本地python数据结构。或即时转换它们。试试看,请:

>>> import elasticsearch
>>> es = elasticsearch.Elasticsearch()
>>> es.index(index='unicode-index', body={'host': u'www.utklädningskläderna.se'}, doc_type='log')

{u'_id': u'AUyGJuFMy0qdfghJ6KwJ',
 u'_index': u'unicode-index',
 u'_type': u'log',
 u'_version': 1,
 u'created': True}

>>> es.search(index='unicode-index', body={}, doc_type='log')

{u'_shards': {u'failed': 0, u'successful': 5, u'total': 5},
 u'hits': {u'hits': [{u'_id': u'AUyBTz5CsiBSSvubLioQ',
    u'_index': u'unicode-index',
    u'_score': 1.0,
    u'_source': {u'host': u'www.utkl\xe4dningskl\xe4derna.se'},
    u'_type': u'log'}],
  u'max_score': 1.0,
  u'total': 1},
 u'timed_out': False,
 u'took': 5}

>>> es.search(index='unicode-index', body={'query': {'match': {'host': u'www.utklädningskläderna.se'}}}, doc_type='log')

{u'_shards': {u'failed': 0, u'successful': 5, u'total': 5},
 u'hits': {u'hits': [{u'_id': u'AUyBTz5CsiBSSvubLioQ',
    u'_index': u'unicode-index',
    u'_score': 0.30685282,
    u'_source': {u'host': u'www.utkl\xe4dningskl\xe4derna.se'},
    u'_type': u'log'}],
  u'max_score': 0.30685282,
  u'total': 1},
 u'timed_out': False,
 u'took': 122}

>>> import json

>>> body={'query': {'match': {'host': u'www.utklädningskläderna.se'}}}

>>> es.search(index='unicode-index', body=body, doc_type='log')

{u'_shards': {u'failed': 0, u'successful': 5, u'total': 5},
 u'hits': {u'hits': [{u'_id': u'AUyBTz5CsiBSSvubLioQ',
    u'_index': u'unicode-index',
    u'_score': 0.30685282,
    u'_source': {u'host': u'www.utkl\xe4dningskl\xe4derna.se'},
    u'_type': u'log'}],
  u'max_score': 0.30685282,
  u'total': 1},
 u'timed_out': False,
 u'took': 4}

>>> es.search(index='unicode-index', body=json.dumps(body), doc_type='log')

{u'_shards': {u'failed': 0, u'successful': 5, u'total': 5},
 u'hits': {u'hits': [{u'_id': u'AUyBTz5CsiBSSvubLioQ',
    u'_index': u'unicode-index',
    u'_score': 0.30685282,
    u'_source': {u'host': u'www.utkl\xe4dningskl\xe4derna.se'},
    u'_type': u'log'}],
  u'max_score': 0.30685282,
  u'total': 1},
 u'timed_out': False,
 u'took': 5}

>>> json.dumps(body)
'{"query": {"match": {"host": "www.utkl\\u00e4dningskl\\u00e4derna.se"}}}'


 类似资料:
  • 问题内容: 我正在针对似乎渴望返回双重UTF-8编码字符串的应用程序进行工作。 我发送使用UTF-8编码的字符串,因此变成(等于)。 服务器 应 仅回显我发送的内容,但返回以下内容:(应为)。如果我将其解码采用变,使用UTF-8,它看起来像一个......的unicode字符串,包含原始字符串编码。 但是Python不允许我在不重新编码的情况下解码unicode字符串-由于某种原因而失败,这使我逃

  • 问题内容: 我正在使用elasticsearch从json文件过滤和搜索,并且我是这项技术的新手。所以我有点困惑如何在elasticsearch中写像查询一样的东西。 这是mysql查询。如何在Elasticsearch中编写此查询?我正在使用Elasticsearch 0.90.7版。 问题答案: 如果可能的话,我强烈建议您更新ElasticSearch版本,自0.9.x版本以来发生了重大变化。

  • Django所有地方都原生地支持Unicode数据。只要你的数据库能存储数据,你就可以安全地把Unicode字符串传递到模板、模型和数据库中。 本文档告诉你如果当你写用到非ASCII的数据或者模板的应用时,你需要知道什么。 创建数据库 确认你的数据库配置可以存储任意字符串数据。一般来讲,这意味着给它一个UTF-8或者UTF-16的编码方式。如果你用了更具约束性的编码 – 例如latin1 (iso

  • 这是mysql查询。如何在ElasticSearch中编写此查询?我使用的是elasticsearch版本0.90.7。

  • 我正在对elasticsearch(1.7)进行常规搜索,使用对许多指定字段的匹配查询。这是在一个java应用程序中完成的,只有一个框可以输入搜索项。允许各种搜索选项(例如,用引号包围短语来查找阶段,而不是成分词)。这意味着我正在进行全面的测试搜索。 一切都很好,除了我的帐户裁判有正斜杠在他们和一个帐户裁判的搜索产生成千上万的结果。如果我用引号包围帐户引用,我就得到了我想要的结果。我假设AC/12

  • 我正在尝试阅读包含以下内容的pdf文件: 如果我打开它,它可以工作,但是如果我尝试使用编解码器.open(文件名,编码=“utf8”,mode=“rb”)来获取unicode字符串,我得到了以下异常: 您知道从此文件的内容中获取 unicode 字符串的方法吗? PS:我使用的是蟒蛇 2.7