爬虫第一课——教你学会使用requests库

爬虫第一课——教你学会使用requests库,第1张

目录

前言

一、发送请求的一些方式

(一)GET

1.url

2.headers

 3.proxies

4.timeout

5.params

6.verify

(二)POST

1.url

2. headers

3.data

4.json

二、对响应数据进行简单处理

(一)response.content

(二)response.apparent_encoding

(二)response.text

(三)response.status_code

1.常见的响应状态码:

2.注意事项

(四)response.request.headers

(五)response.headers

(六)response.url

(七)response.request._cookies

(八)response.cookies

1.将CookieJar类型转换为Cookie

2.将Cookie转换为CookieJar类型 

3.将Cookie转换为Cookie字典

三、requests.session()的使用 

四、爬虫小例子

(一)爬取实习僧职位信息

(二)百度图片下载


前言

在requests库可以说是爬虫中必备的一个第三方库(在python2版本中常用python的内置库urllib,在python3中也常用urllib库的一些模块方便开发)。

由于requests库是第三方库,所有需要安装

pip install requests

requests库是作用简单来说就是:向要爬取的目标网站发送请求,再获取网站的响应数据,然后可以对这些响应数据进行简单处理。

一、发送请求的一些方式

发送请求的方式有七种,爬虫常用的是GET和POST。

(一)GET

# [ ]表示里面的参数为可选参数

response=requests.get(url[, headers, proxies,timeout, params, verify])

下面对其中的参数进行一些详细说明

1.url

url为你要爬取的目标网站的链接,可以直接将url换成链接,也可以写url=目标网站链接 

response=requests.get('http://www.baidu.com')

或者

response=requests.get(url='http://www.baidu.com')

2.headers

headers为请求头,也是网站反爬的重点,查看一个网站的请求头,可以打开目标网站,然后打开开发者工具(或按F12),然后选择Network,再刷新一下网页。这样就可以捕获到网站的请求和响应数据。通常选择左侧Name窗口的第一项,然后选择Headers,Request Headers,我们在爬虫中要添加的请求头都在里面。

 爬虫请求头中最常添加的几个参数如下(直接把浏览器查到的对应项复制过来即可):

(1)Cookie

        用于身份验证和登录的状态保持

(2)Host

        目标网站的主机

(3)Referer

        请求的来源,常用于防盗链

(4)User-Agent

        请求代理,此项是最常见的反爬手段,因为爬虫程序会默认把此参数的值设置为Python啥啥啥,目标网站通过此参数可以判断该请求是否由爬虫程序发出

如果添加了这些参数还不能正常爬取,就尝试再复制添加几个其他的参数,如果全部参数都添加了依旧不能爬取,那么就要在其他方面“动手脚”。

添加方式为,定义一个字典,将以上参数添加到字典中,然后将headers=该字典,例如

headers_dict={

        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'

}

response=requests.get(url,headers=headers_dict)

 3.proxies

当访问一个网站时,你的电脑IP地址会被网站记录下来,如果你访问太过于频繁,网站可能会认定此IP来自一个爬虫程序或者网站遭到了攻击,此时就会把这个IP添加到网站访问的黑名单中,然后再去访问网站时就会什么都获取不到,一般来说IP被封禁后几天就会恢复,但是既然我们是做爬虫的,肯定要求一个时效性,怎么一直等待几天呢?这时就用到了proxies参数。

格式如下

proxies_data={

        'https':'https://ip地址:端口号',        # 用于https的网站

        'http':'http://ip地址:端口号'            # 用于http的网站

}

response=requests.get(url,proxies=proxies_data)

此时网站记录的就是你添加的IP地址,而不是你自己的电脑IP。

那么这些ip地址和端口号去哪获取呢?第一种方式是直接用浏览器搜索“ip代理”,有很多免费的代理可以选择,但是免费的缺点就是ip地址容易失效,不稳定,而且几乎没有https的;推荐使用付费的ip代理,稳定性比较高。

注意:当目标网站是http时,只有http的代理ip会生效;当目标网站是https时,只有https的代理ip会生效。

4.timeout

格式如下

response=requests.get(url,timeout=3)

 作用就是当请求时间超过3秒还未获取到响应时,就会抛出异常,可以使用try...except处理异常。

5.params

用于添加发送get请求时传入的一些参数,可以在开发者工具---Network---Headers---Query String Parameters中看到。

例如我在百度的搜索框中输入“params参数”,然后搜索,然后打开开发者工具,刷新网页就能看到。

 和添加headers一样,定义一个字典,字典中写入以上内容,然后再指定params=此字典即可。

注意:有些参数是每次访问时js算法生成的,直接复制过去没有用,这就需要学习一下JS逆向破解的内容。

6.verify

当浏览器访问网站出现这个提示时,使用爬虫程序请求此网站也会出错,出现这个问题的网站基本都是https的网站,是由于这个网站用到的安全证书已过期,或者这个安全证书是私人的证书,都会提示这个问题的,是网站的问题,不是你电脑或者爬虫的问题。

 解决方式是将verify的值设置为False,表示爬虫程序不验证网站的安全证书,设置为False后爬虫可以正常请求网站,但是会出来一个警告信息(不影响程序运行)

 可以使用如下代码去掉警告~

import urllib3

urllib3.disable_warnings()

response=requests.get(url,verify=False)

(二)POST

格式为

# [ ]表示里面的参数为可选参数

response=requests.post(url[, headers,data,json])

1.url

访问的目标网站链接(同get方法)

2. headers

请求头(同get方法)

3.data

当请求头中的Content-Type为application/x-www-form-urlencoded时,请求的参数,在开发者工具——Network——Headers——Form Data中。

 添加的方式也是先定义一个字典,字典中添加Form Data中的内容,然后将data=此字典。

data_dict={

        ......

        ......

response=requests.post(url,data=data_dict)

4.json

当请求头中的Content-Type为application/json时,表明需要传的是一个json类型的对象,请求的参数,在开发者工具——Network——Headers——Request Payload中。

添加的方式也是先定义一个字典,注意是字典,不需要使用json模块的json.dumps()转成json格式!requests模块会自动转。然后字典中添加Request Payload中的内容,然后将json=此字典。 

json_dict={

        ......

        ......

response=requests.post(url,json=json_dict)

二、对响应数据进行简单处理 (一)response.content

返回原生的响应内容,也就是没有经过任何解码的Byte类型的二进制数据,例如图片、视频、音频、文本等等。

(二)response.apparent_encoding

apparent_encoding会从网页的内容中分析网页编码的方式,可以将此值复制给response.encoding进行解码。

(二)response.text

将 response.content进行解码的字符串,requests会根据自己的猜测来判断采用哪种解码方式,所以有可能会猜测错误,导致页面产生乱码,这时候就应该使用自定义的解码方式来进行解码。 response.content.decode('utf-8'),表示以utf-8的编码方式进行解码,解码的结果为Unicode类型的字符串,也可以使用gbk、gb2312等编码方式,decode()函数的默认解码方式是utf-8。

只能解码文本数据,如果是图片、音视频等不行。

print(response.content.decode())

也可以这样写

response.encoding=response.apparent_encoding

print(response.text)

(三)response.status_code

返回响应的状态码。

1.常见的响应状态码:
200请求成功
302页面跳转,新的URL在响应头的Location参数中给出
303浏览器对于POST的响应进行重定向至新的URL
307       浏览器对于GET的响应重定向至新的URL
403资源不可用,服务器理解客户的请求,但是拒绝处理
404请求的页面在服务器中未找到
500服务器内部错误
503服务器由于维护或负载过重未能应答,在响应头中可能会携带Retry-Afrer响应头;也可能是爬虫频繁访问导致服务器忽视爬虫的请求
2.注意事项

(1)所有的状态码都不可信(因为状态码也是网站的后端程序员写的!),一切都以是否能够抓包得到响应体中的数据为准!就是开发者工具的Network中获取的数据。

(2)一般来讲,如果网站的后端程序员讲武德,会把网站的响应状态码严格按照规定来写,此时应注意,如果response.status_code返回的状态码是4开头,就要尝试切换IP代理。

(四)response.request.headers

返回向网站发送请求时的请求头。

(五)response.headers

返回获取响应时的响应头。

(六)response.url

返回此响应对应的请求的URL。

(七)response.request._cookies

返回此响应对应的请求的Cookie,为CookieJar类型。

(八)response.cookies

返回此响应的Cookie,经过了Set-Cookie的动作,为CookieJar类型。

1.将CookieJar类型转换为Cookie
dict_cookies=requests.utils.dict_from_cookiejar(response.cookies)
print(dict_cookies)
2.将Cookie转换为CookieJar类型 
jar_cookies=requests.utils.cookiejar_from_dict(dict_cookies)
print(jar_cookies)
3.将Cookie转换为Cookie字典
cookies_dict={cookie.split('=')[0]:cookie.split('=')[-1] for cookie in response.cookies.split('; ')}
三、requests.session()的使用 

requests.session()用于会话保持。当使用session成功请求了某个网站,则再次使用此session对象请求该网站的其他网页时都会使用该session对象之前使用的Cookie等参数。

在请求某些网站时,需要登录才能够获取数据,我们不可能做到每请求一次都要去登陆一下,这样太过于繁琐,此时就需要用到session保持会话的功能了,我们可以只登陆一次,然后保持这种状态去完成更多的请求~

使用方法如下:

headers_dict={
    'referer': 'https://github.com/session',
    'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'
}
my_session=requests.session()
my_session.headers=headers_dict
response=my_session.get(url)

设置了session之后,对网站的请求 *** 作还是与之前的requests.get和requests.post一样,只是把requests换成了你自己设置的session对象名。如果headers等参数在定义session对象时已经统一设置过了,那么在get或者post请求中添加的headers等参数会把原来统一设置的headers等参数替换掉。

四、爬虫小例子 (一)爬取实习僧职位信息
import requests
from bs4 import BeautifulSoup
headers={
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'
}

# 获取页面
def getPage(url):
    try:
        re=requests.get(url,headers=headers,timeout=5)
        re.encoding=re.apparent_encoding
        return re.text
    except:
        print('Error!')
        
# 获取详细信息
def getDetail(html):
    soup=BeautifulSoup(html,'03lxml')
    # title=soup.title.text #获取网页标题
    job_name=soup.select('.new_job_name span')[0].text.strip()
    company_name=soup.select('.com_intro .com-name')[0].text.strip()
    salary=getNumber(soup.select('.job_money')[0].text.strip())
    job_week=getNumber(soup.select('.job_week')[0].text.strip())
    job_time=getNumber(soup.select('.job_time')[0].text.strip())
    # print("{:<20}{:<20}{:<10}{:<10}{:<10}".format(job_name,company_name,salary,job_week,job_time))
    print(job_name,company_name,salary,job_week,job_time)

# 字符串解密
def getNumber(text):
    text=text.encode('utf-8')
    text = text.replace(b'\xee\xac\xb1', b'0')
    text = text.replace(b'\xee\x99\xbc', b'1')
    text = text.replace(b'\xef\x82\x81', b'2')
    text = text.replace(b'\xee\xb2\x99', b'3')
    text = text.replace(b'\xef\x97\x92', b'4')
    text = text.replace(b'\xef\x8e\x93', b'5')
    text = text.replace(b'\xef\x96\x9f', b'6')
    text = text.replace(b'\xee\xb8\xb4', b'7')
    text = text.replace(b'\xef\x9e\xb1', b'8')
    text = text.replace(b'\xef\xa1\x99', b'9')
    # 将utf-8的编码解码为字符串,不加这一句,文字和数字均是utf-8编码
    text = text.decode()
    return text

if __name__ == '__main__':
    # print("{:<20}{:<20}{:<10}{:<10}{:<10}".format("职位名称", "公司名称", "薪资", "实习天数", "实习月数"))
    url="https://www.shixiseng.com/interns?page=1&type=intern&keyword=Python&city=北京"
    html_1=getPage(url)
    soup=BeautifulSoup(html_1,'03lxml')
    count=soup.select('.el-pager .number')[-1].text # 页数
    for i in range(1,int(count)+1):
        print(">>>开始爬取第{}页".format(i))
        url='https://www.shixiseng.com/interns?page={}&type=intern&keyword=Python&city=北京'.format(i)
        html=getPage(url) # 获取每个page的url
        soup=BeautifulSoup(html,'03lxml')
        for item in soup.select('.f-l .intern-detail__job a'):
            url_detail=item['href'] #每个职位的详细链接
            html=getPage(url_detail)
            getDetail(html)
(二)百度图片下载
import requests
from urllib import parse
from uuid import uuid4
import os
import time

headers={
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36',
}
session=requests.session()
session.headers=headers
num=0
def getPage(url):
    page=session.get(url)
    print(page.status_code)
    # print(page.json())
    page.encoding=page.apparent_encoding
    data=page.json()['data']    # 列表
    for i in data[:-1]: # 因为最后一个是空的,所以取到倒数第二个元素
        img_url=i['hoverURL']
        print(img_url)
        imgDownload(img_url)

# 下载图片
def imgDownload(url):
    if not os.path.exists('06_imgs'):
        os.makedirs('06_imgs')
    global num
    try:
        content=session.get(url)
        with open('06_imgs/{}.jpg'.format(uuid4()),'wb') as f:
            for chunk in content.iter_content(225): # 每次下载225字节
                if chunk:
                    f.write(chunk)
            num += 1
            print(">>>第{}张爬取成功.".format(num))
    except:
        print(">>>爬取失败.")

if __name__ == '__main__':
    # num=0
    s=time.time()
    word=input("请输入关键词:")
    pages=input("请输入要爬取的页数,每页30张图片:")
    for page in range(int(pages)):
        url='https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&word='+parse.quote(word)+'&pn='+str((page+1)*30)
        getPage(url)
    print(time.time()-s)

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/874681.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存