V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
ElegantOfKing
V2EX  ›  Python

如何使用 Python 得到网页返回正确的 Json 数据?

  •  1
     
  •   ElegantOfKing · 2016-02-27 20:12:55 +08:00 · 13966 次点击
    这是一个创建于 3217 天前的主题,其中的信息可能已经有所发展或是发生改变。
    使用 Python 获取 ’ http://www.fengqu.com/detail/10780.html?_spm=0.sere0.0.3 ‘这上面的商品信息,发现其‘加入购物车’的 div 是用 JS 动态加载的,调用了控制台看了他是 post 网址’ http://www.fengqu.com/m.api ‘来获取一组 Json 数据来判断是否卖光的。

    我尝试加入了 Cookie
    现在问题来了, post 的网址基本上就是一个通用地址,只能从控制台看到它的 form_data 数据,我尝试加入了 Cookie 和 headers 数据,返回的 Json 数据仍然是错误的。
    那么究竟该怎么样获取到正确的 Json 呢?
    16 条回复    2016-03-01 21:38:06 +08:00
    bjrjk
        1
    bjrjk  
       2016-02-27 20:47:37 +08:00   ❤️ 1
    经过测试,你应该是没加 Header : Content-Type: application/x-www-form-urlencoded; charset=UTF-8
    ElegantOfKing
        2
    ElegantOfKing  
    OP
       2016-02-27 20:59:05 +08:00
    @bjrjk 这是我的代码,已经加了您说的字段,然而返回的 code 还是-200 ,不是正常的 code:0 状态

    `
    import requests

    from bs4 import BeautifulSoup

    header = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) '
    'AppleWebKit/537.36 (KHTML, like Gecko)'
    ' Chrome/48.0.2564.109 Safari/537.36',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie':'_uuid=39079e34-7269-4d3b-a672-c1f59086d9cc; __da=-215504379541777; OZ_1U_2363=vid=v6d04247d8202b.0&ctime=1456490248&ltime=1456490243; _jzqx=1.1455543702.1456498125.3.jzqsr=fengqu%2Ecom|jzqct=/detail/10780%2Ehtml.jzqsr=fengqu%2Ecom|jzqct=/detail/10780%2Ehtml; CNZZDATA1256288985=1199591736-1455542262-http%253A%252F%252Fwww.smzdm.com%252F%7C1456499244; CNZZDATA1256279840=156634024-1455541244-http%253A%252F%252Fwww.fengqu.com%252F%7C1456495387; _jzqy=1.1456484530.1456573705.1.jzqsr=baidu.-; _jzqckmp=1; _qzja=1.164100432.1455543702200.1456498125306.1456573704670.1456577134403.1456577787169.0.0.0.66.6; _qzjb=1.1456573704670.13.0.0.0; _qzjc=1; _qzjto=13.1.0; _gat_UA-62706183-1=1; OZ_1U_2295=vid=v6c1d597308ae2.0&ctime=1456577787&ltime=1456577134; OZ_1Y_2295=erefer=http%3A//www.v2ex.com/t/259530&eurl=http%3A//www.fengqu.com/detail/10780.html%3F_spm%3D0.sere0.0.3&etime=1456577787&ctime=1456577787&ltime=1456577134&compid=2295; _ga=GA1.2.379386047.1455543703; _gat=1; tmc=12.44792627.23507604.1456573704972.1456577134824.1456577788347; tma=44792627.55423659.1455545817493.1456484534220.1456573704980.3; tmd=59.44792627.55423659.1455545817493.; bfd_s=44792627.34495851.1456573704968; bfd_g=b1edecf4bbe4880400007449000045ae56c1dddb; _jzqa=1.4354667487562971600.1455543702.1456498125.1456573705.6; _jzqc=1; _jzqb=1.18.10.1456573705.0; _fmdata=99B3EEF20C227339CCC2B93CA24A64E3CE5D86362CD69E984D8ADFD8C8E255226AA2F0AE247D6FB6CF2C6686FC7C5BDDDE12F0222C23A4A3'
    }

    url = requests.post('http://www.fengqu.com/m.api',headers=header)
    print(url)

    `
    ElegantOfKing
        3
    ElegantOfKing  
    OP
       2016-02-27 21:03:14 +08:00
    修改一下格式

    ``` python
    import requests

    from bs4 import BeautifulSoup

    header = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) '
    'AppleWebKit/537.36 (KHTML, like Gecko)'
    ' Chrome/48.0.2564.109 Safari/537.36',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie':'...' # 此处省略若干 Cookie 信息
    }

    url = requests.post('http://www.fengqu.com/m.api',headers=header)
    print(url.json())

    ```
    ss098
        4
    ss098  
       2016-02-27 21:08:12 +08:00 via Android   ❤️ 1
    阅读了你的代码,你只是将协议改为了 POST 而没有提交 POST 数据。

    可以指定 post 函数的 data 参数来提交数据。

    http://www.yangyanxing.com/article/1079.html
    maowu
        5
    maowu  
       2016-02-27 21:08:39 +08:00   ❤️ 1
    能不能把你的实际操作结果发出来呢?我倒是返回了一段 json 数据,但不知道是不是你要的那一段
    ElegantOfKing
        6
    ElegantOfKing  
    OP
       2016-02-27 21:13:30 +08:00
    @ss098
    万分感谢您的资料,已经收到了指定的 Json 数据!
    ElegantOfKing
        7
    ElegantOfKing  
    OP
       2016-02-27 21:14:08 +08:00
    @maowu
    {
    "stat": {
    "cid": "a:5bf5c0|t:20592|s:1456578905083",
    "code": 0,
    "notificationList": [],
    "stateList": [
    {
    "code": 0,
    "length": 345,
    "msg": "成功"
    }
    ],
    "systime": 1456578905100
    },
    "content": [
    {
    "activitySoldOut": true,
    "activityStock": 0,
    "currencySymbol": "Can.$",
    "currentStock": 0,
    "endTime": 0,
    "isPromotion": false,
    "isStartGoods": false,
    "itemId": 10780,
    "limitBuy": 1,
    "localSellingPrice": 5100,
    "originPrice": 24900,
    "productShape": "JSHT",
    "referencePrice": 38900,
    "sellingPrice": 24900,
    "soldOut": true,
    "startTime": 0,
    "status": 3,
    "supportShoppingCart": true
    }
    ]
    }
    ElegantOfKing
        8
    ElegantOfKing  
    OP
       2016-02-27 21:15:18 +08:00
    感谢以上会员的帮助,我已经成功得到了指定的 Json 数据,我把代码发出来,给大家参考一下!

    import requests


    header = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) '
    'AppleWebKit/537.36 (KHTML, like Gecko)'
    ' Chrome/48.0.2564.109 Safari/537.36',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie':'# 此处省略若干 Cookie 信息
    }
    datas = {
    '_mt':'b2cmall.getProductHotData',
    'itemId':'10780',
    '_sm':'md5',
    '_aid':'1',
    '_sig':'5fc1d3ab173bb79b8dd05df36867bc70'
    }

    url = requests.post('http://www.fengqu.com/m.api',data = datas,headers = header)
    print(url.text)
    maowu
        9
    maowu  
       2016-02-27 21:19:10 +08:00
    @ElegantOfKing
    ”_mt “ 你用的是哪一个值?我好像请求到的是优惠信息=。=
    ElegantOfKing
        10
    ElegantOfKing  
    OP
       2016-02-27 21:21:39 +08:00
    @maowu
    网页一共有 7 个 post 请求,我使用的是第 3 个 post 网址,您可能用的是 post 其他网址的 Cookies ,所以出现了优惠的那个请求。

    我用的_mt 的值是 b2cmall.getProductHotData
    webdev
        11
    webdev  
       2016-02-28 00:37:05 +08:00
    楼上的正解是:
    1.Request Header 里最好加上 Content-Type: application/x-www-form-urlencoded; charset=UTF-8
    2. 使用 Post ,个人觉得应该是 requests.post('http://www.fengqu.com/m.api',data = json.dumps(datas),headers = header)
    3. 得到的 Response 也用 json.loads(response.txt)比较保险吧
    ElegantOfKing
        12
    ElegantOfKing  
    OP
       2016-02-28 11:16:28 +08:00
    @webdev
    正解!
    bjrjk
        13
    bjrjk  
       2016-02-28 14:29:59 +08:00 via Android
    hh
    slideclick
        14
    slideclick  
       2016-02-29 16:20:52 +08:00
    @ss098 这 API 设计的有问题, post 的 data 应该是位置参数也就是不可以忽略的
    ss098
        15
    ss098  
       2016-02-29 17:24:19 +08:00 via Android
    @slideclick 在某些情况下确实是有这样的需求的,不一定非要发送 POST 数据,可以只是将协议设定为 POST 。
    SlipStupig
        16
    SlipStupig  
       2016-03-01 21:38:06 +08:00
    {
    "stat": {
    "cid": "a:e4b882|t:89|s:1456839439606",
    "code": 0,
    "notificationList": [],
    "stateList": [
    {
    "code": 0,
    "length": 559,
    "msg": "成功"
    }
    ],
    "systime": 1456839439618
    },
    "content": [
    {
    "value": [
    {
    "activityId": 1144,
    "activityTitle": "全场满 88 包邮",
    "activityType": "POSTAGE_FREE",
    "activityTypeDesc": "满额减邮",
    "appList": [
    "1",
    "3",
    "4",
    "5",
    "601",
    "603"
    ],
    "channelList": [
    "B2C"
    ],
    "endTime": 1476237327000,
    "h5ActivityLink": "http://m.fengqu.com/activity/1641.html",
    "pcActivityLink": "http://www.fengqu.com/activity/1640.html",
    "promotionRules": [
    {
    "bonusesId": 0,
    "cardBagId": 0,
    "cardId": 0,
    "depositPayEnd": 0,
    "depositPayStart": 0,
    "limit": 8800,
    "preferential": 2000,
    "retainagePayEnd": 0,
    "retainagePayStart": 0,
    "ruleDesc": "满 88 包邮"
    }
    ],
    "startTime": 1447293323000
    }
    ]
    }
    ]
    }
    提交数据到 m.api 就行了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5717 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 02:55 · PVG 10:55 · LAX 18:55 · JFK 21:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.