Reputation: 460
When I do this:
s = response.xpath('//meta[@id="_bootstrap-neighborhood_card"]').extract()
what I get back is:
<meta content='{"hosting":{"id":2256573,"offset_lat":39.04258923718809,"offset_lng":-95.69083697887662},"map_url":"https://maps.googleapis.com/maps/api/staticmap?markers=%2C&size&zoom=14","place_recommendations":[],"neighborhood_breadcrumb_details":[{"link_text":"Southwest Fillmore Street,","search_text":"Southwest Fillmore Street Topeka, KS","link":"<span>Southwest Fillmore Street,</span>","link_route":"/s/Southwest-Fillmore-Street-Topeka--KS"},{"link_text":"Topeka,","search_text":"Topeka, KS","link":"<span>Topeka,</span>","link_route":"/s/Topeka--KS"},{"link_text":"Kansas,","search_text":"Kansas, United States","link":"<span>Kansas,</span>","link_route":"/s/Kansas--United-States"},{"link_text":"United States","search_text":"United States","link":"<span>United States</span>","link_route":"/s/United-States"}],"neighborhood_basic_info":null,"neighborhood_localized_name":null,"user_info":{"user_image":"<img alt=\"Elizabeth\" data-pin-nopin=\"true\" height=\"90\" src=\"https://a0.muscache.com/im/users/9199018/profile_pic/1380782460/original.jpg?aki_policy=profile_x_medium\" title=\"Elizabeth\" width=\"90\" />"}}' id="_bootstrap-neighborhood_card">
Which is clearly JSON but it's encoded (as you can see). I tried urllib.unquote
but that throws an error. AttributeError: 'list' object has no attribute 'split'
I was hoping to not have to resort to using a regex to do the URL decoding. What can I do (besides using a regex) to make this valid JSON?
Upvotes: 0
Views: 2242
Reputation: 87094
You can decode using json.loads()
, however, you need to get at the JSON string contained in the content
attribute of <meta>
tag.
You can make multiple calls to xpath()
to drill into the attributes of the selected tag:
meta = response.xpath('//meta[@id="_bootstrap-neighborhood_card"]')
content = meta.xpath('@content').extract_first()
data = json.loads(content)
Or you can do it in one go:
content = response.xpath('//meta[@id="_bootstrap-neighborhood_card"]').xpath('@content').extract_first()
data = json.loads(content)
from pprint import pprint
pprint(data)
Output
{u'hosting': {u'id': 2256573, u'offset_lat': 39.04258923718809, u'offset_lng': -95.69083697887662}, u'map_url': u'https://maps.googleapis.com/maps/api/staticmap?markers=%2C&size&zoom=14', u'neighborhood_basic_info': None, u'neighborhood_breadcrumb_details': [{u'link': u'Southwest Fillmore Street,', u'link_route': u'/s/Southwest-Fillmore-Street-Topeka--KS', u'link_text': u'Southwest Fillmore Street,', u'search_text': u'Southwest Fillmore Street Topeka, KS'}, {u'link': u'Topeka,', u'link_route': u'/s/Topeka--KS', u'link_text': u'Topeka,', u'search_text': u'Topeka, KS'}, {u'link': u'Kansas,', u'link_route': u'/s/Kansas--United-States', u'link_text': u'Kansas,', u'search_text': u'Kansas, United States'}, {u'link': u'United States', u'link_route': u'/s/United-States', u'link_text': u'United States', u'search_text': u'United States'}], u'neighborhood_localized_name': None, u'place_recommendations': [], u'user_info': {u'user_image': u''}}
Upvotes: 1
Reputation: 473933
Get the value of the content
attribute and load it via json.loads()
:
>>> import json
>>> content = response.xpath('//meta[@id="_bootstrap-neighborhood_card"]/@content').extract_first()
>>> json.loads(content)
Note that you also need to use extract_first()
instead of extract()
to get a string value and not a list.
Upvotes: 2