目录
前言
一、发送请求的一些方式
(一)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
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.urlurl为你要爬取的目标网站的链接,可以直接将url换成链接,也可以写url=目标网站链接
2.headersresponse=requests.get('http://www.baidu.com')
或者
response=requests.get(url='http://www.baidu.com')
headers为请求头,也是网站反爬的重点,查看一个网站的请求头,可以打开目标网站,然后打开开发者工具(或按F12),然后选择Network,再刷新一下网页。这样就可以捕获到网站的请求和响应数据。通常选择左侧Name窗口的第一项,然后选择Headers,Request Headers,我们在爬虫中要添加的请求头都在里面。
爬虫请求头中最常添加的几个参数如下(直接把浏览器查到的对应项复制过来即可):
(1)Cookie
用于身份验证和登录的状态保持
(2)Host
目标网站的主机
(3)Referer
请求的来源,常用于防盗链
(4)User-Agent
请求代理,此项是最常见的反爬手段,因为爬虫程序会默认把此参数的值设置为Python啥啥啥,目标网站通过此参数可以判断该请求是否由爬虫程序发出
如果添加了这些参数还不能正常爬取,就尝试再复制添加几个其他的参数,如果全部参数都添加了依旧不能爬取,那么就要在其他方面“动手脚”。
添加方式为,定义一个字典,将以上参数添加到字典中,然后将headers=该字典,例如
3.proxiesheaders_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)
当访问一个网站时,你的电脑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后爬虫可以正常请求网站,但是会出来一个警告信息(不影响程序运行)
可以使用如下代码去掉警告~
(二)POSTimport urllib3
urllib3.disable_warnings()
response=requests.get(url,verify=False)
格式为
1.url# [ ]表示里面的参数为可选参数
response=requests.post(url[, headers,data,json])
访问的目标网站链接(同get方法)
2. headers请求头(同get方法)
3.data当请求头中的Content-Type为application/x-www-form-urlencoded时,请求的参数,在开发者工具——Network——Headers——Form Data中。
添加的方式也是先定义一个字典,字典中添加Form Data中的内容,然后将data=此字典。
4.jsondata_dict={
......
......
}
response=requests.post(url,data=data_dict)
当请求头中的Content-Type为application/json时,表明需要传的是一个json类型的对象,请求的参数,在开发者工具——Network——Headers——Request Payload中。
添加的方式也是先定义一个字典,注意是字典,不需要使用json模块的json.dumps()转成json格式!requests模块会自动转。然后字典中添加Request Payload中的内容,然后将json=此字典。
二、对响应数据进行简单处理 (一)response.contentjson_dict={
......
......
}
response=requests.post(url,json=json_dict)
返回原生的响应内容,也就是没有经过任何解码的Byte类型的二进制数据,例如图片、视频、音频、文本等等。
(二)response.apparent_encodingapparent_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.status_coderesponse.encoding=response.apparent_encoding
print(response.text)
返回响应的状态码。
1.常见的响应状态码:200 | 请求成功 |
302 | 页面跳转,新的URL在响应头的Location参数中给出 |
303 | 浏览器对于POST的响应进行重定向至新的URL |
307 | 浏览器对于GET的响应重定向至新的URL |
403 | 资源不可用,服务器理解客户的请求,但是拒绝处理 |
404 | 请求的页面在服务器中未找到 |
500 | 服务器内部错误 |
503 | 服务器由于维护或负载过重未能应答,在响应头中可能会携带Retry-Afrer响应头;也可能是爬虫频繁访问导致服务器忽视爬虫的请求 |
(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类型转换为Cookiedict_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)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)