TipError: Obiectul de tip ‘bytes’ nu este serializabil JSON (Programare, Python, Json, Serializare, Scrapy)

Zhibin a intrebat.

Tocmai am început să programez Python. Vreau să folosesc scrapy pentru a crea un bot,și a arătat TypeError: Object of type ‘bytes’ is not JSON serializable când am rulat proiectul.

import json
import codecs

class W3SchoolPipeline(object):

  def __init__(self):
      self.file = codecs.open('w3school_data_utf8.json', 'wb', encoding='utf-8')

  def process_item(self, item, spider):
      line = json.dumps(dict(item)) + '
'
      # print line

      self.file.write(line.decode("unicode_escape"))
      return item

from scrapy.spiders import Spider
from scrapy.selector import Selector
from w3school.items import W3schoolItem

class W3schoolSpider(Spider):

    name = "w3school"
    allowed_domains = ["w3school.com.cn"]

    start_urls = [
        "http://www.w3school.com.cn/xml/xml_syntax.asp"
    ]

    def parse(self, response):
        sel = Selector(response)
        sites = sel.xpath('//div[@id="navsecond"]/div[@id="course"]/ul[1]/li')

    items = []
    for site in sites:
        item = W3schoolItem()
        title = site.xpath('a/text()').extract()
        link = site.xpath('a/@href').extract()
        desc = site.xpath('a/@title').extract()

        item['title'] = [t.encode('utf-8') for t in title]
        item['link'] = [l.encode('utf-8') for l in link]
        item['desc'] = [d.encode('utf-8') for d in desc]
        items.append(item)
        return items

Traceback:

TypeError: Object of type 'bytes' is not JSON serializable
2017-06-23 01:41:15 [scrapy.core.scraper] ERROR: Error processing       {'desc': [b'x
e4xbdxbfxe7x94xa8 XSLT xe6x98xbexe7xa4xba XML'],
 'link': [b'/xml/xml_xsl.asp'],
 'title': [b'XML XSLT']}

Traceback (most recent call last):
File  
"c:usersadministratorappdatalocalprogramspythonpython36libsite-p
ackagestwistedinternetdefer.py", line 653, in _runCallbacks
    current.result = callback(current.result, *args, **kw)
File "D:LZZZZBw3schoolw3schoolpipelines.py", line 19, in process_item
    line = json.dumps(dict(item)) + '
'
File 
"c:usersadministratorappdatalocalprogramspythonpython36libjson_
_init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
File 
"c:usersadministratorappdatalocalprogramspythonpython36libjsone
ncoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
File  
"c:usersadministratorappdatalocalprogramspythonpython36libjsone
ncoder.py", line 257, in iterencode
    return _iterencode(o, 0)
File      
"c:usersadministratorappdatalocalprogramspythonpython36lib
jsonencoder.py", line 180, in default
    o.__class__.__name__)
  TypeError: Object of type 'bytes' is not JSON serializable

4 răspunsuri
Martijn Pieters

Creați aceste bytes singuri aceste obiecte:

item['title'] = [t.encode('utf-8') for t in title]
item['link'] = [l.encode('utf-8') for l in link]
item['desc'] = [d.encode('utf-8') for d in desc]
items.append(item)

Fiecare dintre aceste t.encode(), l.encode() și d.encode() creează un obiect bytes șir de caractere. Nu faceți acest lucru, lăsați formatul JSON să le serializeze.

În continuare, faceți alte câteva erori; codificați prea mult acolo unde nu este nevoie. Lăsați acest lucru în seama formatului json și modulul standard file object returnat de către open() să se ocupe de codificare.

De asemenea, nu trebuie să convertiți items într-un dicționar; aceasta va fi deja un obiect care poate fi codificat direct în JSON:

class W3SchoolPipeline(object):    
    def __init__(self):
        self.file = open('w3school_data_utf8.json', 'w', encoding='utf-8')

    def process_item(self, item, spider):
        line = json.dumps(item) + '
'
        self.file.write(line)
        return item

Presupun că ați urmat un tutorial care presupunea Python 2, în schimb, dumneavoastră folosiți Python 3. Vă sugerez cu tărie să găsiți un alt tutorial; nu numai că este scris pentru o versiune depășită de Python, dacă pledează pentru line.decode('unicode_escape') acesta învață niște obiceiuri extrem de proaste care vor duce la bug-uri greu de depistat. Vă pot recomanda să vă uitați la Think Python, ediția a 2-a pentru o carte bună, gratuită, pentru a învăța Python 3.

Jordan Donovan

M-am confruntat cu această problemă astăzi și știam că aveam ceva codificat ca un obiect bytes pe care încercam să îl serializez ca json cu json.dump(my_json_object, write_to_file.json). my_json_object în acest caz era un obiect json foarte mare pe care îl creasem, așa că aveam mai multe dicte, liste și șiruri la care trebuia să mă uit pentru a găsi ceea ce era încă în format bytes.

Modul în care am sfârșit prin a rezolva problema: the write_to_file.json va avea totul până la obiectul bytes care cauzează problema.

În cazul meu particular, acesta era o linie obținută prin

for line in text:
    json_object['line'] = line.strip()

Am rezolvat găsind mai întâi această eroare cu ajutorul fișierului write_to_file.json, apoi corectând-o în:

for line in text:
    json_object['line'] = line.strip().decode()

Furqan Ali

Pur și simplu scrieți <variable name>.decode("utf-8").

De exemplu:

myvar = b'asdqweasdasd'
myvar.decode("utf-8")

Sreeja Nampoothiri

Cred că răspunsul de care aveți nevoie este menționat aici Seturile Python nu sunt serializabile json

Nu toate tipurile de date pot fi serializate json . Cred că modulul pickle va servi scopului tău.

Comentarii

    16

  • Oh, omule, cât de greșit… Sper că nu plănuiești ca OP să trimită cuiva date serializate în pickle de la un serviciu web la un client care nu rulează Python! –  > Por Dagrooms.
  • Întrebarea lui OP este despre json dumping, și asta în cazul de utilizare a comunicațiilor între două limbaje diferite, cum ar fi Python și Javascript. pickle este o soluție doar pentru python, care nu va rezolva problema aici. –  > Por Jinghui Niu.