2019-11-18 爬网页5-爬基于post请求的网页(requests,还有一些编码困惑)

前面学习了seleniumm模块来爬post请求的网页,但是速度很慢,因为实际要打开火狐网页来操作。
现在我们改用requests模块来爬。

使用网站https://www.mcdonalds.com.cn/top/map,查找麦当劳餐厅,获得指定条件的餐厅信息。
这个网页的获得餐厅数据的相关函数就在主页html中,截取如下
view-source:https://www.mcdonalds.com.cn/top/map

 $('#search_ipt,#search_ipt_mobile').autocomplete({
            source: function (request, response) {
                var str = $.trim(request.term);
                if (str == '') {
                    return;
                }
                avl_map.search_poi(str);
            }
        });

 var avl_map = avalon.define({
       ......
        search_poi: function (val) {
                if (val.length > 1) {
                    $.post('/ajaxs/search_by_keywords', {
                        keywords: val,
                        city: cityinfo
                    }, function (rsp) {
                        var rtn = $.parseJSON(rsp);
                        if (rtn.info && rtn.info == 'OK') {
                            avl_map.searchResult = rtn.tips;
                            avl_map.searched = 1;
                        }
                    });
                }
            }

search_ipt就是输入条件的文本域。

很明显了,我们感兴趣的网址就是https://www.mcdonalds.com.cn/ajaxs/search_by_keywords,请求方式是post,参数有2个keywords和city。返回是json类型。

我们可以测试一下,捕获网络信息在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上面3图很明显了,网址,请求方式,参数,返回值都有了

爬网页代码如下:

# -*- coding: utf8 -*-
import requests
import json

# 指定post请求的url
url1 = 'https://www.mcdonalds.com.cn/ajaxs/search_by_keywords'

# 处理post请求携带的参数
data1 = {
    'keywords':'上海青浦',
    'city':'上海市'
}

# 自定义请求头信息,相关的头信息必须封装在字典结构中
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36',
}

# 发起post请求
response = requests.post(url=url1,data=data1,headers=headers)
#print response.encoding   #获取当前的编码,uft8

#获取响应内容:json对象
data = response.text #json格式字符串
data = json.loads(data) #把json字符串转化为python字典类型
print data
with codecs.open('1.csv', 'wb', encoding='gbk') as f: #保存文件
    for i in data["tips"]:
        print i['address'] #原始数据
        output='\t'.join([str(i['city']),str(i['name']),str(i['district']),str(i['address']),str(i['id'])]);
        f.write(output);
        f.write('\n');

在这里插入图片描述

文件内容如上图

后记,编码的困惑

代码开发用的是utf8编码,获得页面编码也是utf8(print response.encoding)。

但是把json字符串转化为python字典类型之后,data = json.loads(data),获得的是unicode类型。打印一下print type(data),data,结果如下:

<type 'dict'> {u'status': u'1', u'count': u'10', u'tips': [{u'city': [], u'name': u'\u767e\u8054\u5965\u7279\u83b1\u65af\u5e7f\u573a', u'district': u'\u4e0a\u6d77\u5e02\u9752\u6d66\u533a', u'typecode': u'060101', u'adcode': u'310118', u'location': u'121.228317,31.156196', u'address': u'\u5609\u677e\u4e2d\u8def5555\u53f7', u'id': u'B001571JFR'}, {u'city': [], u'name': u'\u9752\u6d66\u533a', u'district': u'\u4e0a\u6d77\u5e02\u9752\u6d66\u533a', u'typecode': u'190105', u'adcode': u'310118', u'location': u'121.124178,31.150681', u'address': [], u'id': u'B00155PTBK'}, {u'city': [], u'name': u'\u534e\u65b0\u9547', u'district': u'\u4e0a\u6d77\u5e02\u9752\u6d66\u533a', u'typecode': u'190106', u'adcode': u'310118', u'location': [], u'address': [], u'id': []}, {u'city': [], u'name': u'\u9752\u6d66\u5ba2\u8fd0\u7ad9', u'district': u'\u4e0a\u6d77\u5e02\u9752\u6d66\u533a', u'typecode': u'150400', u'adcode': u'310118', u'location': u'121.087549,31.158655', u'address': u'\u76c8\u6e2f\u8def2043\u53f7', u'id': u'B001541AD1'}, {u'city': [], u'name': u'\u590d\u65e6\u5927\u5b66\u9644\u5c5e\u4e2d\u5c71\u533b\u9662\u9752\u6d66\u5206\u9662', u'district': u'\u4e0a\u6d77\u5e02\u9752\u6d66\u533a', u'typecode': u'090100', u'adcode': u'310118', u'location': u'121.137482,31.155454', u'address': u'\u516c\u56ed\u4e1c\u8def1158\u53f7', u'id': u'B00150B219'}, {u'city': [], u'name': u'\u56fd\u5bb6\u4f1a\u5c55\u4e2d\u5fc3(\u4e0a\u6d77)', u'district': u'\u4e0a\u6d77\u5e02\u9752\u6d66\u533a', u'typecode': u'140300', u'adcode': u'310118', u'location': u'121.302151,31.189984', u'address': u'\u5d27\u6cfd\u5927\u9053333\u53f7', u'id': u'B0FFFDXOI4'}, {u'city': [], u'name': u'\u543e\u60a6\u5e7f\u573a', u'district': u'\u4e0a\u6d77\u5e02\u9752\u6d66\u533a', u'typecode': u'060101', u'adcode': u'310118', u'location': u'121.095092,31.144145', u'address': u'\u6dc0\u5c71\u6e56\u5927\u9053218\u53f7', u'id': u'B00157I0E6'}, {u'city': [], u'name': u'\u6731\u5bb6\u89d2\u53e4\u9547', u'district': u'\u4e0a\u6d77\u5e02\u9752\u6d66\u533a', u'typecode': u'110202', u'adcode': u'310118', u'location': u'121.053951,31.109319', u'address': u'\u6731\u5bb6\u89d2\u9547', u'id': u'B001558F5I'}, {u'city': [], u'name': u'\u767d\u9e64\u9547', u'district': u'\u4e0a\u6d77\u5e02\u9752\u6d66\u533a', u'typecode': u'190106', u'adcode': u'310118', u'location': [], u'address': [], u'id': []}, {u'city': [], u'name': u'\u4e0a\u6d77\u5e02\u9752\u6d66\u533a\u4eba\u6c11\u653f\u5e9c', u'district': u'\u4e0a\u6d77\u5e02\u9752\u6d66\u533a', u'typecode': u'130104', u'adcode': u'310118', u'location': u'121.123948,31.150668', u'address': u'\u516c\u56ed\u8def100\u53f7', u'id': u'B00150BA3D'}], u'info': u'OK', u'infocode': u'10000'}

此时我的DOS窗口编码936(gbk)

C:\>chcp
活动代码页: 936

打印地址

 for i in data["tips"]:
        print i['address']

结果如下

?嗡芍新?555号Traceback (most recent call last):
  File "kfc.py", line 52, in <module>
    print i['address']
IOError: [Errno 0] Error

我的理解是编码转换的问题。所以改变一下DOS窗口编码,65001(utf8)

C:\>chcp 65001
Active code page: 65001

运行后直接报错

Traceback (most recent call last):
  File "kfc.py", line 51, in <module>
    print i['address']
LookupError: unknown encoding: cp65001

最后,我再把编码改回936

C:\>chcp 936
活动代码页: 936

现在再打印地址,结果显示正常了

嘉松中路5555号
[]
[]
盈港路2043号
公园东路1158号
崧泽大道333号
淀山湖大道218号
朱家角镇
[]
公园路100号

实在是不理解怎么回事情。
我只是做了把936改65001,再改回936,结果就能显示正常了。

发布了122 篇原创文章 · 获赞 7 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_42555985/article/details/103124476