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()