1,requests的get请求的发送
- 什么是requests模块:requests模块是Python中原生的基于网络请求的模块,其主要作用是用来模拟浏览器发起请求.功能强大,用简洁高效的语言,在爬虫领域占据着半壁*的位置
- requests向比较与urllib的request的极大优势:
- 不用手动处理url编码
- 不用手动处理post请求参数
- 不用处理cookie和繁琐的代理操作
- requests模块的使用
- 安装:pip install requets
- 使用requests
- 指定要请求的url
- 基于requests模块发起请求
- 获取响应对象中的数据值
- 持久化存储
2,具体相关代码:
import requests
import os
# 指定搜索关键字
word = input("enter a word you want to search:")
# 自定义请求头信息
headers = {
"User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
}
# 指定url
url = "https://www.sogou.com/web"
# 封装get请求参数
params = {
"query": word,
"ie": "utf-8"
}
# 向网址发请求
response = requests.get(url=url, params=params)
print(response)
# <Response [200]>
# 获取响应数据
page_text = response.text
# 持久化存储
with open("./sougou.html", "w", encoding="utf-8") as fp:
fp.write(page_text)
- 请求载体的身份表示的伪装:
- User-Agent:请求载体身份标识,通过浏览器发起的请求,请求载体为浏览器,则该请求的User-Agent为浏览器的身份标识,使用爬虫程序发起的请求,则该请求的载体为爬虫程序,则该请求的User-Agent为爬虫程序的身份标识,可以通过判断值来获取该请求的载体究竟是基于 浏览器还是基于爬虫程序来的
- 反爬机制:某些门户网会对访问该网站的请求中User-Agent进行捕获和判断,如果该请求的UA为爬虫程序,则拒绝向该请求提供该数据
- 反反爬策略:将爬虫程序的UA伪装成某一款浏览器的身份标识
爬取豆瓣电影,爬取登录成功后的页面数据
# 2豆瓣电影的数据的抓取(ajax的get请求的发送)
import requests
import os
# 发情求的url
url = "https://movie.douban.com/typerank"
# 制定请求头的信息,相关的头信息必须封装在字典结构中
headers = {
"User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
}
# 定制get请求携带的参数
param = {
"type": "13",
"interval_id": "100:90",
"actions": "",
"limit": "20",
}
# 发get请求, 获取响应对象
response = requests.get(url=url, headers=headers, params=param)
print(response.text)
requests模块的post请求
import requests
import os
url = "https://accounts.douban.com/j/mobile/login/basic"
# 封装请求的参数
data = {
"ck":"",
"name": "18731229751",
"password": "jiji0923",
"remember": "false",
"ticket":""
}
# 自定义请求头信息
headers = {
"User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
}
response = requests.post(url=url, data=data)
print(response)
page_text = response.text
# 持久化存储
with open("./douban.html", "w", encoding="utf-8") as fp:
fp.write(page_text)
requests模块的ajax请求
import requests
if __name__ == '__main__':
print(123)
# 指定ajax-post请求的url(通过浏览器获取)
url = "http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword"
# 定制请求头信息,相关信息封装在字典结构中
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
}
print(456)
# 定制post请求携带的参数(从浏览器装包中获取到network)
data = {
"cname": "",
"pid": "",
"keyword": "北京",
"pageIndex": "1",
"pageSize": "10",
}
# 发送post请求的信息,获取响应对象
print("哈哈哈")
response = requests.post(url=url, headers=headers, data=data)
print(789)
# 获取响应内容,响应内容为串
print(response.text)
- 获取食药监中华人名*关于化妆品生产许可的数据
import requests
from fake_useragent import UserAgent
ua = UserAgent(use_cache_server=False, verify_ssl=False)
headers = {
"User-Agent": ua
}
url = "http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsList"
# 定义一个全局的变量
pageNum = 3
for page in range(3,5):
data = {
"on": "true",
"page": str(page),
"pageSize": "15",
"productName": "",
"conditionType": "2",
"applyname":"",
"applysn":""
}
# 发送请求
json_text = requests.post(url=url, data=data, headers=headers).json()
all_id_list = []
# 循环这个响应字典的列表,拿到每一个信息
for dict in json_text["list"]:
id = dict["ID"]
all_id_list.append(id)
# 发送post请求获取详情数据
post_url = "http://125.35.6.84:81/xk/itownet/portal/dzpz.jsp"
for id in all_id_list:
post_data = {
"id": id
}
response = requests.post(url=post_url, data=post_data, headers=headers)
if response.headers["Content-Type"] == "application/json;charset=UTF-8":
json_text = response.json()
print(json_text["businessPerson"])
小结:在爬取数据的时候,如果是是get请求获取到的是html页面,一般获取到的响应对象的text即可,如果是post请求,服务器返回的响应json格式的数据(尤其是ajax请求,返回的数据),数据采集的步骤如下:
- 获取目标数据页面的url
- 定制User-Agent请求头,浏览器的伪装
- 如果是get请求就直接用requests发送get请求,拿到响应体.text
- 如果是post请求就需要定制post的请求携带参数data
- 如果有二级页面的数据,需要再根据二次页面的url,在指定请求的参数发送请求,详情见KFC和国家药监总局
3,requests的session处理cookie
- 在有些时候我们在爬取一些用户相关信息的时候,如果使用之前的requests模块常规操作,往往会达不到想要的效果
- 在requests中的cookie的操作:
- cookie概念:当用户通过浏览器收悉访问一个域名时,访问web服务器会给客户端发送数据,以保持web服务器与客户端之间状态保持,这些就是cookie
- cookie的作用:我们在浏览器中,经常涉及到数据的交换,比如登录邮箱,登录一个页面的时候,我们经常会在此设置30天记住我,或者自动登录状态,他们是怎么记录信息的呢?Cookie是有HTTP服务器设置的,保存在浏览器中,但HTTP协议是一种无状态协议,在数据交换完毕后,服务器和客户端,浏览器和服务器的连接就会关闭,每次交换数据都是需要建立新的连接,就想我们去超市买东西,没有积分卡的时候,我们买完东西后超市没哟无偶们任何的消费信息,但是我们办了积分卡后,可以保存积分,商品就是我们的信息,超市的系统就想我们服务器的后台,http协议就是交易的过程
- 思路:
- 我们需要使用爬虫程序对人人网的登录是的请求进行一次抓取,获取请求中的cookie
- 在使用个人信息页的url进行请求时,该请求要携带撒花姑娘变的cookie,服务器才可再次识别再次请求的用户信息,方可响应指定用户页面的信息
import requests
if __name__ == '__main__':
# 登录请求的url
post_url = "http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=2019062051812"
# 创建一个session对象,该对象会自动将请求中的cookie进行存储和携带
session = requests.session() # requests中有一个session对象
# 伪装UA
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
}
# post请求要提交的数据
formdata = {
"email": "18731229751",
"icode": "",
"origURL": "http://www.renren.com/home",
"domain": "renren.com",
"key_id": "1",
"captcha_type": "web_login",
"password": "054c50afb1d1c5f6bc9e45954178a019f0e3b01ea098c68964201846148cdb78",
"rkey": "39b392090c635431e86ef76d46f31f40",
"f": "http%3A%2F%2Fwww.renren.com%2F969397800",
}
# 使用session发送请求,目的是为了将session保存该次请求中的cookie
session.post(url=post_url, data=formdata, headers=headers)
get_url = "http://www.renren.com/969397800"
# 如果在此发送请求的时候,这时session中已经携带了cookie
response = session.get(url=get_url, headers=headers)
# 设置响应格式内容的编码
response.encoding = "utf-8"
#将响应的内容写入到文件中
with open("./renren.html","w") as fp:
fp.write(response.text)
4基于requests的代理操作
- 什么是代理:代理就是代替第三方本体处理年相关事务
- 爬虫中为什们需要使用代理:
- 一些网站会有相应的反爬虫措施,列如很多网站会检测某一段时间某个人IP的访问时间,如果访问频率太快以至于太快看起来不像正常的访客,它可能就会禁止这个IP的访问,所有我们需要一些代理IP,每个一段时间换一个IP,就算IP被禁止,依然可以换个IP继续爬取
- 代理的分类:
- 正向代理:代理客户端获取数据,正向代理是为了保护客户端防止被追究责任
- 反向代理:代理服务器提供该数据,反向代理是为了保护服务器或负责负载均衡
- 免费代理IP:百度很多,一搜便是
单线程的数据抓取:
# 梨视频数据的爬取
import requests
import random
from lxml import etree
import re
from fake_useragent import UserAgent
# 安装fake_useragent: pip install fake_useragent
url = "https://www.pearvideo.com/category_8"
ua = UserAgent().random
# 定制请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
}
# 获取首页页面数据
page_text = requests.get(url=url, headers=headers).text
# print("111", page_text)
# 获取首页页面数据的相关视频详情连接进行解析
tree = etree.HTML(page_text)
li_list = tree.xpath("//div[@id='listvideoList']/ul/li")
print("哈哈哈", li_list)
# 详情的url
detail_urls = [] # type:list
for li in li_list:
detail_url = "http://www.pearvideo.com/" + li.xpath("./div/a/@href")[0] # 此时返回的是一个列表
print("222",detail_url)
title = li.xpath("./div/a/div[@class='vervideo-title']/text()")[0]
detail_urls.append(detail_url)
print(detail_urls)
# 拿到每一个详情url发送get请求
for url in detail_urls:
page_text = requests.get(url=url, headers=headers).text
video_url = re.findall('srcUrl="(.*?)"', page_text, re.S)[0]
print("啧啧啧", video_url)
# 向视频的详情发送请求
data = requests.get(url=video_url, headers=headers).content
fileName = str(random.randint(1,10000)) + '.mp4' # 随机生成视频文件
# 存储得到本地
with open(fileName, "wb") as fp:
fp.write(data)
print(fileName + "下载成功!")
线程池的数的爬取:
import requests
from lxml import etree
import re
import random
# 开一个线程池
from multiprocessing.dummy import Pool
pool = Pool(5)
def saveVideo(data):
name = str(random.randint(0,10000)) + ".mp4"
with open(name, "wb") as fp:
fp.write(data)
print(name + "下载成功!")
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
}
# 拿到梨视频的url
url = "https://www.pearvideo.com/category_8"
page_text = requests.get(url=url, headers=headers).text
tree = etree.HTML(page_text)
# 拿到的是每一个视频对应的url
li_list=tree.xpath("//div[@id='listvideoList']/ul/li/div/a/@href") # '//ul[@class="listvideo-list clearfix"]/li/div/a/@href'
print(li_list)
# 准备一个列表去存放视频的url
video_url_list = []
# 拼接视频的详细url
for li in li_list:
detail_page_url = "https://www.pearvideo.com/" + li
# 发请求
detail_page_text = requests.get(url=detail_page_url, headers=headers).text
# 这样呀,还没拿到视频的url只拿到一个关于url的i标签和img标签
video_url = re.findall('srcUrl="(.*?)"', detail_page_text, re.S)[0]
print(video_url)
video_url_list.append(video_url)
# 并发瞎下载视频
downloadVideo = lambda link: requests.get(url=link, headers=headers).content
# map 返回的是列表中存储的下载完毕的二进制的视频
video_data_list = pool.map(downloadVideo, video_url_list)
# 把每一个二进制视频写进文件中
pool.map(saveVideo, video_data_list)
pool.close()
pool.join()