爬虫学习记录-3

  • ajax的get请求

该案例为请求电影的第一页,前几步和之前一样

url = 'https://movie.douban.com/j/chart/top_list?type=17&interval_id=100%3A90&action=&start=0&limit=20'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76'}
request = urllib.request.Request(url=url,headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')

此时需要将数据下载到本地,将文件下载到本地可以用以下方法

fp = open('douban.json','w')
fp.write(content)

但是会出现报错:UnicodeEncodeError: 'gbk' codec can't encode character '\xf8' in position 8546: illegal multibyte sequence

后经了解得知是因为保存的数据有中文,所以保存的时候需要将数据编码

fp = open('douban.json','w',encoding='utf-8')

  • 案例:请求豆瓣电影前十页数据

①首先将该过程封装成函数,先写主函数,从键盘输入起始和结束页码,此步要注意的是input方法返回值是字符串类型,要转成整型

start_page = int(input('请输入起始页码'))
end_page = int(input('请输入结束页码'))

②因为要遍历1~10页,所以需要用到for page in range结构,又因为每一页都要经历请求对象定制、获得响应数据、下载数据三步,所以需要在此结构下定义一个方法,使每一页都有自己请求对象的定制,即create_request(),随后写改方法

该方法的重点在于每一页的url不同,需要找到规律,而url里有两个参数,由于请求方法为get请求,参数只需urlencode拼接而不用如post请求传入参数,由于其中的start参数和page页码有关,因此可以将for page in range结构中的page作为参数传递给create_request()方法,即create_request(page)

def create_request(page):
    base_url = 'https://movie.douban.com/j/chart/top_list?type=17&interval_id=100%3A90&action=&'
    data = {
        'start':(page-1)*20,
        'limit':20
    }
    data = urllib.parse.urlencode(data)
    url = base_url + data
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76'}
    request = urllib.request.Request(url=url,headers=headers)

③接下来就是获得响应数据,定义get_content()方法,response = urllib.request.urlopen(),由于urlopen()中需要传进request参数,所以需要request返回值,即在create_request()函数添加一步return request将request返回,并将其接收,再将其传给get_content()方法,最后get_content()方法中就可以调用request

request = create_request(page)
content = get_content(request)

④最后下载数据,定义down_load()方法,因为所下载的文件名不能一致,所以可以传入page参数实现以下操作,又因为保存的数据有中文,所以保存的时候需要将数据编码,加上encoding='utf-8'

fp = open('douban_' + page + 'json','w',encoding='utf-8')

然后fp.write()写入内容content,但该函数中没有此参数,所以需要在get_content()函数的最后一步添加return content将其返回,并经其接收,再将content传给down_load()方法,最后down_load()方法就可以调用content

down_load(page,content)


def down_load(page,content):
    fp = open('douban_' + page + 'json','w',encoding='utf-8')
    fp.write(content)

运行结果出现错误,原因在于字符串拼接时,两端必须是str型,而page为整形,所以需将page转换为字符串型:str(page)

fp = open('douban_' + str(page) + 'json','w',encoding='utf-8')
def create_request(page):
    base_url = 'https://movie.douban.com/j/chart/top_list?type=17&interval_id=100%3A90&action=&'
    data = {
        'start':(page-1)*20,
        'limit':20
    }
    data = urllib.parse.urlencode(data)
    url = base_url + data
    #此处出现一个问题:AttributeError: 'tuple' object has no attribute 'items'        解决方法是headers格式错误,{}后加了个,
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76'}
    request = urllib.request.Request(url=url,headers=headers)
    return request

def down_load(page,content):
    fp = open('douban_' + str(page) + 'json','w',encoding='utf-8')
    fp.write(content)

def get_content(request):
    response = urllib.request.urlopen(request)
    content = response.read().decode('utf-8')
    return content

if __name__ == '__main__':
    start_page = int(input('请输入起始页码'))
    end_page = int(input('请输入结束页码'))

    for page in range(start_page,end_page+1):
        request = create_request(page)
        content = get_content(request)
        down_load(page,content)

最后成功

*注:使用Ctrl+alt+L可以方便转换格式便于查看

  • Ajax的post请求

此案例为请求肯德基官网餐厅位置

当点开检查,Headers往下看到X-Requested-With:XMLHttpRequest,这是ajax的核心对象,此时可以知道这是一个ajax请求,查看Request URL和From DATA可以找到每页的规律,然后其他步骤和上个案例基本一致。

需要注意的是data的格式为字典,其中参数需要加上'',并且页码的不同取决于pageIndex,因此可以将page参数传入create_request()方法。

且post请求参数必须要转换成Unicode编码拼接,并在Request()传入data参数

def create_request(page):
    base_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'
    data = {
        'cname': '石家庄',
        'pid':'',
        'pageIndex': page,
        'pageSize': 10,
    }
    data = urllib.parse.urlencode(data).encode('utf-8')
    headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76'}
    request = urllib.request.Request(url=base_url,headers=headers,data=data)
    return request

全部代码如下

def create_request(page):
    base_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'
    data = {
        'cname': '石家庄',
        'pid':'',
        'pageIndex': page,
        'pageSize': 10,
    }
    data = urllib.parse.urlencode(data).encode('utf-8')
    headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76'}
    request = urllib.request.Request(url=base_url,headers=headers,data=data)
    return request

def get_content(request):
    response = urllib.request.urlopen(request)
    content = response.read().decode('utf-8')
    return content

def down_load(page,content):
    fp = open('kfc_' + str(page) +'.json','w',encoding='utf-8')
    fp.write(content)

if __name__ == '__main__':
    start_page = int(input('请输入起始页码'))
    end_page = int(input('请输入结束页码'))

    for page in range(start_page,end_page):
        requset = create_request(page)
        content = get_content(requset)
        down_load(page,content)

*注:在手打代码过程中我出现了一个混淆decode和encode的问题,主要原因还是对其理解的不清楚,随后查阅了他们的区别如下:decode就是把二进制数据 (bytes)转化成人看的懂得英文或者汉字 (decode用的比较多) ,encode的作用是将unicode编码的字符串编码成二进制数据

  • urllib异常

一般会出现两种报错,一种是HTTPError,另一种是URLError。

出现URLError一般为①网络没有连接、②服务器连接失败、③找不到指定的服务器(主机地址或参数出现问题)

出现HTTPError则可以根据返回对应的状态码知道http具体状态

异常格式如下(首先要导入urllib.error包)

try:
    request = urllib.request.Request(url=url,headers=headers)
    response = urllib.request.urlopen(request)
    content = response.read().decode('utf-8')
    print(content)
except urllib.error.HTTPError:
    print('系统正在升级')
except urllib.error.URLError:
    print('系统正在升级,请稍后再试')

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值