source

MongoDB 잘못된 문서: 개체를 인코딩할 수 없습니다.

ittop 2023. 7. 6. 22:35
반응형

MongoDB 잘못된 문서: 개체를 인코딩할 수 없습니다.

저는 스크레이피를 사용하여 블로그를 스크랩한 다음 데이터를 mongodb에 저장하고 있습니다.처음에는 잘못된 문서 예외가 발생했습니다.제가 보기에 데이터가 올바른 인코딩이 아니라는 것이 분명합니다.그래서 개체를 유지하기 전에 MongoPipeline에서 문서가 'utf-8 strict'에 있는지 확인한 다음 mongodb에 개체를 유지하려고 합니다. 그래도 잘못된 문서 예외가 발생합니다. 이제 짜증이 납니다.

이것은 mongodb에 개체를 유지하는 내 코드 my MongoPipelineObject입니다.

# -*- coding: utf-8 -*-

# Define your item pipelines here
#

import pymongo
import sys, traceback
from scrapy.exceptions import DropItem
from crawler.items import BlogItem, CommentItem


class MongoPipeline(object):
    collection_name = 'master'

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get('MONGO_URI'),
            mongo_db=crawler.settings.get('MONGO_DATABASE', 'posts')
        )

    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):

        if type(item) is BlogItem:
            try:
                if 'url' in item:
                    item['url'] = item['url'].encode('utf-8', 'strict')
                if 'domain' in item:
                    item['domain'] = item['domain'].encode('utf-8', 'strict')
                if 'title' in item:
                    item['title'] = item['title'].encode('utf-8', 'strict')
                if 'date' in item:
                    item['date'] = item['date'].encode('utf-8', 'strict')
                if 'content' in item:
                    item['content'] = item['content'].encode('utf-8', 'strict')
                if 'author' in item:
                    item['author'] = item['author'].encode('utf-8', 'strict')

            except:  # catch *all* exceptions
                e = sys.exc_info()[0]
                spider.logger.critical("ERROR ENCODING %s", e)
                traceback.print_exc(file=sys.stdout)
                raise DropItem("Error encoding BLOG %s" % item['url'])

            if 'comments' in item:
                comments = item['comments']
                item['comments'] = []

                try:
                    for comment in comments:
                        if 'date' in comment:
                            comment['date'] = comment['date'].encode('utf-8', 'strict')
                        if 'author' in comment:
                            comment['author'] = comment['author'].encode('utf-8', 'strict')
                        if 'content' in comment:
                            comment['content'] = comment['content'].encode('utf-8', 'strict')

                        item['comments'].append(comment)

                except:  # catch *all* exceptions
                    e = sys.exc_info()[0]
                    spider.logger.critical("ERROR ENCODING COMMENT %s", e)
                    traceback.print_exc(file=sys.stdout)

        self.db[self.collection_name].insert(dict(item))

        return item

그리고 여전히 다음과 같은 예외가 있습니다.

au coeur de l\u2019explosion de la bulle Internet n\u2019est probablement pas \xe9tranger au succ\xe8s qui a suivi. Mais franchement, c\u2019est un peu court comme argument !Ce que je sais dire, compte tenu de ce qui pr\xe9c\xe8de, c\u2019est quelles sont les conditions pour r\xe9ussir si l\u2019on est vraiment contraint de rester en France. Ce sont des sujets que je d\xe9velopperai dans un autre article.',
     'date': u'2012-06-27T23:21:25+00:00',
     'domain': 'reussir-sa-boite.fr',
     'title': u'Peut-on encore entreprendre en France ?\t\t\t ',
     'url': 'http://www.reussir-sa-boite.fr/peut-on-encore-entreprendre-en-france/'}
    Traceback (most recent call last):
      File "h:\program files\anaconda\lib\site-packages\twisted\internet\defer.py", line 588, in _runCallbacks
        current.result = callback(current.result, *args, **kw)
      File "H:\PDS\BNP\crawler\crawler\pipelines.py", line 76, in process_item
        self.db[self.collection_name].insert(dict(item))
      File "h:\program files\anaconda\lib\site-packages\pymongo\collection.py", line 409, in insert
        gen(), check_keys, self.uuid_subtype, client)
    InvalidDocument: Cannot encode object: {'author': 'Arnaud Lemasson',
     'content': 'Tellement vrai\xe2\x80\xa6 Il faut vraiment \xc3\xaatre motiv\xc3\xa9 aujourd\xe2\x80\x99hui pour monter sa bo\xc3\xaete. On est pr\xc3\xa9lev\xc3\xa9 de partout, je ne pense m\xc3\xaame pas \xc3\xa0 embaucher, cela me co\xc3\xbbterait bien trop cher. Bref, 100% d\xe2\x80\x99accord avec vous. Le probl\xc3\xa8me, je ne vois pas comment cela pourrait changer avec le gouvernement actuel\xe2\x80\xa6 A moins que si, j\xe2\x80\x99ai pu lire il me semble qu\xe2\x80\x99ils avaient en t\xc3\xaate de r\xc3\xa9duire l\xe2\x80\x99IS pour les petites entreprises et de l\xe2\x80\x99augmenter pour les grandes\xe2\x80\xa6 A voir',
     'date': '2012-06-27T23:21:25+00:00'}
    2015-11-04 15:29:15 [scrapy] INFO: Closing spider (finished)
    2015-11-04 15:29:15 [scrapy] INFO: Dumping Scrapy stats:
    {'downloader/request_bytes': 259,
     'downloader/request_count': 1,
     'downloader/request_method_count/GET': 1,
     'downloader/response_bytes': 252396,
     'downloader/response_count': 1,
     'downloader/response_status_count/200': 1,
     'finish_reason': 'finished',
     'finish_time': datetime.datetime(2015, 11, 4, 14, 29, 15, 701000),
     'log_count/DEBUG': 2,
     'log_count/ERROR': 1,
     'log_count/INFO': 7,
     'response_received_count': 1,
     'scheduler/dequeued': 1,
     'scheduler/dequeued/memory': 1,
     'scheduler/enqueued': 1,
     'scheduler/enqueued/memory': 1,
     'start)
    time': datetime.datetime(2015, 11, 4, 14, 29, 13, 191000)}

@eLRulli의 댓글에서 또 다른 재미있는 점은 다음과 같습니다.

>>> s = "Tellement vrai\xe2\x80\xa6 Il faut vraiment \xc3\xaatre motiv\xc3\xa9 aujourd\xe2\x80\x99hui pour monter sa bo\xc3\xaete. On est pr\xc3\xa9lev\xc3\xa9 de partout, je ne pense m\xc3\xaame pas \xc3\xa0 embaucher, cela me"
>>> s
'Tellement vrai\xe2\x80\xa6 Il faut vraiment \xc3\xaatre motiv\xc3\xa9 aujourd\xe2\x80\x99hui pour monter sa bo\xc3\xaete. On est pr\xc3\xa9lev\xc3\xa9 de partout, je ne pense m\xc3\xaame pas \xc3\xa0 embaucher, cela me'
>>> se = s.encode("utf8", "strict")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 14: ordinal not in range(128)
>>> se = s.encode("utf-8", "strict")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 14: ordinal not in range(128)
>>> s.decode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 14: ordinal not in range(128)

그러면 제 질문은.이 텍스트를 인코딩할 수 없는 경우.그렇다면 왜 내 MongoPipeline 시도 캐치가 이 예외를 감지하지 못하는 것입니까?예외를 발생시키지 않는 개체만 항목에 추가해야 하기 때문에 ['comments']?

마침내 저는 그것을 알아냈습니다.인코딩에 문제가 없습니다.그것은 문서의 구조와 관련이 있었습니다.

왜냐하면 나는 중첩된 스크랩 항목을 다루지 않는 표준 MongoPipeline 예제에서 벗어났기 때문입니다.

제가 하고 있는 일은: 블로그 아이템: "url" ... 댓글 = [댓글항목]

그래서 내 블로그 항목에 댓글 목록이 있습니다.항목. 이제 문제가 발생했습니다. 데이터베이스에서 개체를 유지하는 것에 대한 문제입니다.

self.db[self.collection_name].insert(dict(item))

그래서 저는 블로그 항목을 딕트로 구문 분석하고 있습니다.그러나 댓글 목록을 구문 분석하지 않습니다.항목입니다. 그리고 트레이스백에 댓글이 표시되기 때문입니다.딕트 같은 아이템, 문제가 있는 오브젝트가 딕트가 아니라는 생각이 들지 않았습니다!

마지막으로 이 문제를 해결하는 방법은 다음과 같이 주석을 주석 목록에 추가할 때 줄을 변경하는 것입니다.

item['comments'].append(dict(comment))

이제 MongoDB는 그것을 유효한 문서로 간주합니다.

마지막으로 스크립트가 아닌 파이썬 콘솔에서 예외가 발생하는 이유를 묻는 부분입니다.

그 이유는 제가 아스키만 지원하는 파이썬 콘솔을 작업하고 있었기 때문입니다.그래서 오류가 발생했습니다.

쿼리를 실행할 때 이 오류가 발생했습니다.

db.collection.find({'attr': {'$gte': 20}})

그리고 몇몇 기록들은.collection에 대해 유효하지 않은 값이 있습니다.attr.

첫번째로, 당신이 할때."somestring".encode(...)변하지 않음"somestring"그러나 새 인코딩된 문자열을 반환하므로 다음과 같은 방법을 사용해야 합니다.

 item['author'] = item['author'].encode('utf-8', 'strict')

다른 필드도 마찬가지입니다.

Mongo 쿼리에서 numpy 배열을 사용하여 동일한 오류가 발생했습니다.

'myField' : { '$in': myList },

해결책은 단순히 변환하는 것이었습니다.nd.array()목록으로:

'myField' : { '$in': list(myList) },

나의 경우, 그것은 매우 멍청했지만 알아차리기 쉽지 않았습니다.

실수로 글을 썼습니다.

f"indexes_access.{jsonData['index']}: {jsonData['newState']}"

대신에

{f"indexes_access.{jsonData['index']}": f"{jsonData['newState']}"}

(키와 값을 별도로 구문 분석하는 대신 f 문자열로 구문 분석하는 긴 문자열 하나)

언급URL : https://stackoverflow.com/questions/33524517/mongodb-invaliddocument-cannot-encode-object

반응형