欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python-爬虫(2)---requests库

程序员文章站 2022-03-22 16:55:45
...

今天来聊一下我们爬虫中必不可少的一个强大的库requests,如果大家没有这个包千万不要忘记在我们最爱的cmd当中pip install一下哦。当然request库中有很多的方法,我这个博主小白也只是接触了一点点而已,如果有写的不对的地方,也请大家给我留言,我会及时纠正的。
当然,根据博主的风格,咱们最开始当然还是要做一个比较大的总结啦,来来来,上图。
Python-爬虫(2)---requests库
接下来,我们就开始进入今天的主题了,讲一下requests库的具体使用。

requests.get()方法

我们知道很多网址其实都是get方法,怎么知道网址是get方法还是post方法呢?我们可以查看的哦,首先将打开一个网址然后点右键选择检查,然后选择network之后,刷新一下就可以得到很多莫名其妙的文件,可以随意选择一个,当然一定不要选择图片、音频、视频这种,最好是XHR或者是HTML以及XML这种,在 header 中的general中就能够找到Request Method,这里会有get或者是post。这样我们就知道到底是get还是post方法啦。当然由博主微博的经验来说,一般输入账号密码等都是post方法哦。咱们的例子如题

Python-爬虫(2)---requests库

res.stats_code

这个方法能够查看请求之后的状态码,通常我们打印输出看到是200就皆大欢喜了,如果不是200,总会觉得内心咯噔一下。

content()&text()

这一对姐妹花我们当然也是不得不提的,因为她俩是我的最爱,不管请求怎么网页,我总是喜欢打印一下她们。这两个方法都是获取html内容的方法,但究竟有什么不同呢?说她们的不同,当然需要特殊的字体提醒一下,以后可千万不要混了。
content()的内容是字节形式,我们要想正常显示的话,一定要使用decode(“utf-8”)解码;text()的内容用是字符串形式的,如果想要正常显示中文的话,要用encoding(“utf-8”)编码。 但还有需要注意的是,不一定是utf-8,要看网页的chat-set是什么,如果网页是gbk,我们也要进行相应的修改哦。

get方法中的关键字kwargs

看到关键字或许有疑问,这个关键字是做什么用的,关键字一般是帮助我们进行网址拼接 ,比如我想要在百度上搜索周杰伦哥哥,这里我们就可以使用上关键字了,https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6
噗 这到底是什么,根据我们二十多年来问小度的经常当然会知道我们这是百度了一个什么东西,可是复制之后怎么字就变化了呢?这个时候我们又不得不说说URL中的编码和解码的了(原理没有办法,小白不懂)。如果下次你的损友用不怀好意的表情给你发了一个网址,我们抱着损友不可靠的想法,一定要解码看一下到底发了什么,万一是什么少儿不宜的网站,那我们岂不是超级吃亏。

res = requests.utils.unquote("%E5%91%A8%E6%9D%B0%E4%BC%A6")
print(res)
res = requests.utils.quote("周杰伦")
print(res)

headers&proxies

headers是什么呢?在上一篇笔记中提到了各种头,没错猜对了,因为get方法是请求,当然headers就是我们需要加上的请求头了。
为什么需要加请求头呢?因为爬虫的速度比人点击速度快,很容易被服务器识别从而禁止访问,因此我们需要模拟正常的浏览器去欺骗服务器
既然提到了headers,那么proxies也一定不能忘记,代理有什么作用呢?
代理的作用与headers类似,但是代理更加安全,我们使用代理IP的话可以隐藏自己的真实IP,另一方面,也能够组成一个IP池,让服务器认为是不同的IP访问的

url = "https://www.baidu.com"
proxies = {
    "HTTPS":"60.167.113.79:9999",
    "HTTPS":"1.197.16.63:9999",

}
res = requests.get(url, proxies=proxies)
print(res)

不知道这两个代理IP是否还能够使用,毕竟是几天前找的了,如果不能,要自己找找哦。

一个小例子

好了好了,前面说了那么多,咱们来一个小例子,结束get()方法吧。

import requests

header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"}
# res = requests.get("http://www.swu.edu.cn/", headers=header)
# print(res)
# print(res.status_code) #打印状态码
# print(res.headers)    # 打印反应头
# print(res.request.headers)  #打印请求头

# 下载图片
# url = "http://www.swu.edu.cn/images/notice/292.jpg"
# picture = requests.get(url)
#
# with open("swu.png", "wb") as f:
#     f.write(picture.content)

百度贴吧小例子

class TiebaSpider(object):
    def __init__(self, kw):
        self.kw = kw
        self.url = "https://tieba.baidu.com/f?" + self.kw + "&ie=utf-8&pn={}"
        self.header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"}

    def url_list(self):
        # 获取网址的列表
        return [self.url.format(i*50) for i in range(10)]

    def request_url(self,url):
        # 请求url地址
        res = requests.get(url, headers=self.header)
        # res.encoding("utf-8")
        # content = res.text
        return res.text

    def save_text(self,content,page_num):
        # 保存获取的页面
        with open("{}_第{}页.txt".format(self.kw, page_num), "w+") as f:
            f.write(content)

    def run(self):
        url_list = self.url_list()
        page_num = 0
        for url in url_list:
            url_content = self.request_url(url)
            url_content.encode(encoding='utf-8')
            # print(url_content)
            # exit()
            page_num += 1
            self.save_text(url_content, page_num)


if __name__ == "__main__":
    TS = TiebaSpider("周杰伦")
    TS.run()

timeout&assert

如果指定了timeout=3一般是请求这个网址超过三秒就结束了,并不会再次请求,但是怎么在请求不成功时再次请求呢,如果请求成功了就不再请求了,当然循环加上判断肯定可以实现,但是如何用外部方法实现呢?这个时候可以使用retry方法。代码实现如下:

import requests
from retrying import retry


header = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
}

@retry(stop_max_attempt_number=3)
#在超时的情况下,让代码重复执行几次,如果请求一次就成功了的话,就不会重复执行
def _parse_url(url):
    print("代码执行了几次?")
    res = requests.get(url, headers=header, timeout=3)
    assert res.status_code == 200
    return res.content.decode()


def parse_url(url):
    try:
        html_str = _parse_url(url)
    except:
        html_str = None

    return html_str


if __name__ == '__main__':
    url = 'https://www.baidsu.com'
    # print(parse_url(url))
    parse_url(url)

requests.post()方法

Emmm~ 目前为止,我的post方法学的并不怎么好,这一点自己也是知道的,所以关于post方法我就不自己赘述了,给出老师笔记的网址(居然老师爬虫教程

#发送POST请求
# 百度翻译案例

# data = {
#     'from':' zh',
#     'to':' en',
#     'query':' 翻译',
#     'transtype':' translang',
#     'simple_means_flag':' 3',
#     'sign':' 31941.303092',
#     'token':' bbfb7b73aadf7414e2a54a40a39c157b',
# }
#
# post_url = "https://fanyi.baidu.com/v2transapi?from=zh&to=en"
# res = requests.post(post_url, data=data, headers=header)
# print(res.text)
# PC端与手机端的区别就是请求头不一样

session&cookie

我们利用session和cookie可以获取登录后网页内容,使用方法以登录人人网为例

# session和cookie 保存用户信息
# 登录人人网
# session = requests.session()
# url = "http://www.renren.com/PLogin.do"
# post_data ={
#     "emial":"aaa@qq.com",
#     "password":"*******",
#     }
# # cookie保存在其中
# session.post(url, data=post_data, headers=header)
#
# res = session.get("http://www.renren.com/973411857/newsfeed/photo", headers=header)
# print(res)

# header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
#           "Cookie":"anonymid=k57gya8e-5x01gg; depovince=GW; _r01_=1; ick_login=09eb4eb4-0402-4722-80ae-81a5110082b8; taihe_bi_sdk_uid=8a4532b966136e9c7567787490ea64cb; taihe_bi_sdk_session=1416785d026288e239dbe4d6d8f8f1e8; loginfrom=null; jebe_key=efcf56f9-1bfb-4624-a3b6-756e7d32e7b6%7Cddeaa5791216f5acf04b825b64bc0fa2%7C1578619044992%7C1%7C1578619044919; _de=FAA24AFD253015DB247380B22A94C474696BF75400CE19CC; t=a9f3f05577d82c4855119f41118679817; societyguester=a9f3f05577d82c4855119f41118679817; id=973411857; xnsid=72759b24; jebecookies=1748263d-5acd-4e20-b63a-0b1d5b35b19e|||||; ver=7.0; wp_fold=0"
#           }
#
# res = requests.get("http://www.renren.com/973411857/newsfeed/photo",headers=header)
# with open("qinghuan.html","w",encoding="utf-8") as f:
#     f.write(res.text)

cookie = "anonymid=k57gya8e-5x01gg; depovince=GW; _r01_=1; ick_login=09eb4eb4-0402-4722-80ae-81a5110082b8; taihe_bi_sdk_uid=8a4532b966136e9c7567787490ea64cb; taihe_bi_sdk_session=1416785d026288e239dbe4d6d8f8f1e8; loginfrom=null; jebe_key=efcf56f9-1bfb-4624-a3b6-756e7d32e7b6%7Cddeaa5791216f5acf04b825b64bc0fa2%7C1578619044992%7C1%7C1578619044919; _de=FAA24AFD253015DB247380B22A94C474696BF75400CE19CC; t=a9f3f05577d82c4855119f41118679817; societyguester=a9f3f05577d82c4855119f41118679817; id=973411857; xnsid=72759b24; jebecookies=1748263d-5acd-4e20-b63a-0b1d5b35b19e|||||; ver=7.0; wp_fold=0"
Cookie = {i.split('=')[0]:i.split('=')[1] for i in cookie.split(';')}
# print(Cookie)
res = requests.get("http://www.renren.com/973411857/newsfeed/photo", headers=header, cookies=cookie)
print(res)

requests库中有函数可以将cookie对象转换为字典,也能够将字典转换为cookie对象。

#将cookie对象转为字典, 字典转为cookie对象
# url = "https://www.baidu.com"
# header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'}
# res = requests.get(url, headers=header)
# cookies = requests.utils.dict_from_cookiejar(res.cookies)
# # 把字典转化为cookies对象是cookiejar_from_dict()
# print(cookies)
# a = requests.utils.cookiejar_from_dict(cookies)
# print(a)

json数据

JSON是一种轻量级的数据交换格式,它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。适用于进行数据交互的场景,比如网站前台与后台之间的数据交互。(关于json数据更多的内容,参考居然老师爬虫教程
请求头添加:https://curl.trillworks.com/

练习代码的小案例

这个案例是爬取王者荣耀英雄的个数,这个网址是一个标准的json数据,但是我也不知道这个网址是怎么来的。

#英雄列表URL地址
import requests
import os
from urllib.request import urlretrieve
def main(url, header):
    res = requests.get(url, headers=header)
    req = res.json()
    hero_num = len(req['list'])
    print("一共有{}位英雄" .format(hero_num))
    hero_images_path = "hero_images"
    if not os.path.exists(hero_images_path):
        os.mkdir(hero_images_path)
    hero_list = req['list']
    for each_hero in hero_list:
        hero_photo_url = each_hero['cover']
        hero_name = each_hero['name'] + '.jpg'
        filename = hero_images_path + '/' +hero_name
        print("正在下载{}的图片" .format(each_hero['name']))
        urlretrieve(url=hero_photo_url, filename=filename)
        # 根据url地址下载图片,第一个参数是地址,第二个参数是文件路径
        # with open('{}'.format(filename), 'wb') as f:
        #       f.write()


if __name__ == '__main__':
    heros_url = "http://gamehelper.gm825.com/wzry/hero/list"
    header = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
    }
    main(heros_url, header)