GraphQL 查询 Post with Python Request
Posted
技术标签:
【中文标题】GraphQL 查询 Post with Python Request【英文标题】:GraphQL query Post with Python Request 【发布时间】:2021-01-23 16:27:59 【问题描述】:我一直在尝试使用 Python 发布请求以从网站上抓取一些 json 数据。我没有使用 GraphQL 的经验,但我认为这个网站是用它构建的。所以无论如何,问题是即使我使用 POST 方法请求它,它也会不断返回“GRAPHQL_PARSE_FAILED”(我将在下面发布结果)。我猜这是因为我的查询中包含一个“向左拐角的向下箭头”。由于消息说它无法解析'\u21B5'。
这是代码。
self.API_URL = 'https://pcmap-api.place.naver.com/graphql'
def get_location_info(self, query, start):
header =
'authority': 'pcmap-api.place.naver.com',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/85.0.4183.121 Safari/537.36'
query = """
"query getRestaurants($input: RestaurantsInput, $isNmap: Boolean!, $isBounds: Boolean!) ↵ restaurants(input: $input) ↵ total↵ items ↵ ...RestaurantItemFields↵ easyOrder ↵ easyOrderId↵ easyOrderCid↵ businessHours ↵ weekday ↵ start↵ end↵ __typename↵ ↵ weekend ↵ start↵ end↵ __typename↵ ↵ __typename↵ ↵ __typename↵ ↵ baemin ↵ businessHours ↵ deliveryTime ↵ start↵ end↵ __typename↵ ↵ closeDate ↵ start↵ end↵ __typename↵ ↵ temporaryCloseDate ↵ start↵ end↵ __typename↵ ↵ __typename↵ ↵ __typename↵ ↵ yogiyo ↵ businessHours ↵ actualDeliveryTime ↵ start↵ end↵ __typename↵ ↵ bizHours ↵ start↵ end↵ __typename↵ ↵ __typename↵ ↵ __typename↵ ↵ __typename↵ ↵ nlu ↵ ...NluFields↵ __typename↵ ↵ brand ↵ name↵ isBrand↵ type↵ menus ↵ order↵ id↵ images ↵ url↵ desc↵ __typename↵ ↵ name↵ desc↵ price↵ isRepresentative↵ detailUrl↵ orderType↵ catalogId↵ source↵ menuId↵ nutrients↵ allergies↵ __typename↵ ↵ __typename↵ ↵ optionsForMap @include(if: $isBounds) ↵ maxZoom↵ minZoom↵ includeMyLocation↵ maxIncludePoiCount↵ center↵ spotId↵ __typename↵ ↵ __typename↵ ↵↵↵fragment RestaurantItemFields on RestaurantSummary ↵ id↵ dbType↵ name↵ businessCategory↵ category↵ description↵ hasBooking↵ hasNPay↵ x↵ y↵ distance↵ imageUrl↵ imageUrls↵ imageCount↵ phone↵ virtualPhone↵ routeUrl↵ streetPanorama ↵ id↵ pan↵ tilt↵ lat↵ lon↵ __typename↵ ↵ roadAddress↵ address↵ commonAddress↵ blogCafeReviewCount↵ bookingReviewCount↵ totalReviewCount↵ bookingReviewScore↵ bookingUrl↵ bookingBusinessId↵ talktalkUrl↵ options↵ promotionTitle↵ agencyId↵ businessHours↵ microReview↵ tags↵ priceCategory↵ broadcastInfo ↵ program↵ date↵ menu↵ __typename↵ ↵ michelinGuide ↵ year↵ star↵ comment↵ url↵ hasGrade↵ isBib↵ alternateText↵ __typename↵ ↵ broadcasts ↵ program↵ menu↵ episode↵ broadcast_date↵ __typename↵ ↵ tvcastId↵ naverBookingCategory↵ saveCount↵ uniqueBroadcasts↵ isDelivery↵ markerLabel @include(if: $isNmap) ↵ text↵ style↵ __typename↵ ↵ imageMarker @include(if: $isNmap) ↵ marker↵ markerSelected↵ __typename↵ ↵ isTableOrder↵ isPreOrder↵ isTakeOut↵ bookingDisplayName↵ bookingVisitId↵ bookingPickupId↵ popularMenuImages ↵ name↵ price↵ bookingCount↵ menuUrl↵ menuListUrl↵ imageUrl↵ isPopular↵ usePanoramaImage↵ __typename↵ ↵ visitorReviewCount↵ visitorReviewScore↵ detailCid ↵ c0↵ c1↵ c2↵ c3↵ __typename↵ ↵ streetPanorama ↵ id↵ pan↵ tilt↵ lat↵ lon↵ __typename↵ ↵ __typename↵↵↵fragment NluFields on Nlu ↵ queryType↵ user ↵ gender↵ __typename↵ ↵ queryResult ↵ ptn0↵ ptn1↵ region↵ spot↵ tradeName↵ service↵ selectedRegion ↵ name↵ index↵ x↵ y↵ __typename↵ ↵ selectedRegionIndex↵ otherRegions ↵ name↵ index↵ __typename↵ ↵ property↵ keyword↵ queryType↵ nluQuery↵ businessType↵ cid↵ branch↵ franchise↵ titleKeyword↵ location ↵ x↵ y↵ default↵ longitude↵ latitude↵ dong↵ si↵ __typename↵ ↵ noRegionQuery↵ priority↵ showLocationBarFlag↵ themeId↵ filterBooking↵ repRegion↵ repSpot↵ dbQuery ↵ isDefault↵ name↵ type↵ getType↵ useFilter↵ hasComponents↵ __typename↵ ↵ type↵ category↵ __typename↵ ↵ __typename↵↵"
"""
data =
'operationName': "getRestaurants",
'query': query,
'variables': 'input':
'deviceType': "pcmap",
'display': "50",
'isNmap': "false",
'query': query,
'start': start
,
'isBound': 'true',
'isNmap': 'false'
r = requests.post(self.API_URL, headers=header, json=data).json()
正如您在查询中看到的,它具有 GraphQL 无法解析的箭头。我猜我必须将“查询”转换为 GraphQL 可以理解的某种形式。但这有点令人沮丧,因为我刚刚复制并粘贴了 Request Payload 刚刚显示的内容。我将查询放在 data 参数之外,因为它看起来太乱了。
这是结果。
"errors": [
"extensions":
"code": "GRAPHQL_PARSE_FAILED"
,
"locations": [
"column": 89,
"line": 1
],
"message": "Syntax Error: Cannot parse the unexpected character \"\\u21B5\".",
"status": 500
]
我真的很感激你能想办法解决这个问题。谢谢!
【问题讨论】:
【参考方案1】:你的query
变量应该没有花括号,你应该用'\n'替换所有'↵'符号:
query = "query getRestaurants($input: RestaurantsInput, $isNmap: Boolean!, $isBounds: Boolean!) \n restaurants(input: $input) \n total\n items \n ...RestaurantItemFields\n easyOrder \n easyOrderId\n easyOrderCid\n businessHours \n weekday \n start\n end\n __typename\n \n weekend \n start\n end\n __typename\n \n __typename\n \n __typename\n \n baemin \n businessHours \n deliveryTime \n start\n end\n __typename\n \n closeDate \n start\n end\n __typename\n \n temporaryCloseDate \n start\n end\n __typename\n \n __typename\n \n __typename\n \n yogiyo \n businessHours \n actualDeliveryTime \n start\n end\n __typename\n \n bizHours \n start\n end\n __typename\n \n __typename\n \n __typename\n \n __typename\n \n nlu \n ...NluFields\n __typename\n \n brand \n name\n isBrand\n type\n menus \n order\n id\n images \n url\n desc\n __typename\n \n name\n desc\n price\n isRepresentative\n detailUrl\n orderType\n catalogId\n source\n menuId\n nutrients\n allergies\n __typename\n \n __typename\n \n optionsForMap @include(if: $isBounds) \n maxZoom\n minZoom\n includeMyLocation\n maxIncludePoiCount\n center\n spotId\n __typename\n \n __typename\n \n\n\nfragment RestaurantItemFields on RestaurantSummary \n id\n dbType\n name\n businessCategory\n category\n description\n hasBooking\n hasNPay\n x\n y\n distance\n imageUrl\n imageUrls\n imageCount\n phone\n virtualPhone\n routeUrl\n streetPanorama \n id\n pan\n tilt\n lat\n lon\n __typename\n \n roadAddress\n address\n commonAddress\n blogCafeReviewCount\n bookingReviewCount\n totalReviewCount\n bookingReviewScore\n bookingUrl\n bookingBusinessId\n talktalkUrl\n options\n promotionTitle\n agencyId\n businessHours\n microReview\n tags\n priceCategory\n broadcastInfo \n program\n date\n menu\n __typename\n \n michelinGuide \n year\n star\n comment\n url\n hasGrade\n isBib\n alternateText\n __typename\n \n broadcasts \n program\n menu\n episode\n broadcast_date\n __typename\n \n tvcastId\n naverBookingCategory\n saveCount\n uniqueBroadcasts\n isDelivery\n markerLabel @include(if: $isNmap) \n text\n style\n __typename\n \n imageMarker @include(if: $isNmap) \n marker\n markerSelected\n __typename\n \n isTableOrder\n isPreOrder\n isTakeOut\n bookingDisplayName\n bookingVisitId\n bookingPickupId\n popularMenuImages \n name\n price\n bookingCount\n menuUrl\n menuListUrl\n imageUrl\n isPopular\n usePanoramaImage\n __typename\n \n visitorReviewCount\n visitorReviewScore\n detailCid \n c0\n c1\n c2\n c3\n __typename\n \n streetPanorama \n id\n pan\n tilt\n lat\n lon\n __typename\n \n __typename\n\n\nfragment NluFields on Nlu \n queryType\n user \n gender\n __typename\n \n queryResult \n ptn0\n ptn1\n region\n spot\n tradeName\n service\n selectedRegion \n name\n index\n x\n y\n __typename\n \n selectedRegionIndex\n otherRegions \n name\n index\n __typename\n \n property\n keyword\n queryType\n nluQuery\n businessType\n cid\n branch\n franchise\n titleKeyword\n location \n x\n y\n default\n longitude\n latitude\n dong\n si\n __typename\n \n noRegionQuery\n priority\n showLocationBarFlag\n themeId\n filterBooking\n repRegion\n repSpot\n dbQuery \n isDefault\n name\n type\n getType\n useFilter\n hasComponents\n __typename\n \n type\n category\n __typename\n \n __typename\n\n"
另外,您的布尔值实际上是字符串,您需要像这样定义它们:
'variables':
'input':
...
'isNmap': False,
...
,
'isBound': True,
'isNmap': False
【讨论】:
更新了我的答案 嗯,它返回给我一个内部服务器错误。 '$isNmap' 和 '$isBounds' 没有提供'Boolean!' 我不确定这意味着什么,但我真的很困惑,因为我在 data 参数中的每个中都插入了布尔值。我不确定 graphql 是如何工作的,但是当我看到 Initiators 时,它是从很多 .js 调用的。 我已经尝试了你的建议,我想我们差不多了。但是我仍然无法获取数据,所以我在下面发布了我收到的 json。以上是关于GraphQL 查询 Post with Python Request的主要内容,如果未能解决你的问题,请参考以下文章
为啥即使我们尝试获取数据而不是更新/提交新数据,GraphQL 也会查询 POST 请求?
看起来 apollo 客户端不会查询 id 具有 . (点)使用 Next JS 和 Sanity CMS with GraphQL