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

尝试在 Java 中使用 HttpClient 发送 HTTP Post GraphQL 查询时出现 HTTP 400

Apollo 中的 GraphQL 持久化查询

使用 axios 请求 graphql 查询

Graphql 突变查询不适用于 express-graphql