1. 基于requests模块的代理IP操作
- 爬虫中为什么需要使用代理
一些网站会有相应的反爬虫措施,例如很多网站会检测某一段时间某个IP的访问次数,如果访问频率太快以至于看起来不像正常访客,它可能就会会禁止这个IP的访问。所以我们需要设置一些代理IP,每隔一段时间换一个代理IP,就算IP被禁止,依然可以换个IP继续爬取。
- 代理的分类:
正向代理:代理客户端获取数据。正向代理是为了保护客户端防止被追究责任。
反向代理:代理服务器提供数据。反向代理是为了保护服务器或负责负载均衡。
- 免费代理ip提供网站
http://www.goubanjia.com/
西刺代理
快代理
- 匿名度:
- 透明:知道是代理ip,也会知道你的真实ip
- 匿名:知道是代理ip,不会知道你的真实ip
- 高匿:不知道是代理ip,不会知道你的真实ip
- 类型:
- http:只能请求http开头的url
- https:只能请求https开头的url
示例:可添加多个,构建代理池
1 import requests 2 headers = { 3 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36' 4 } 5 url = 'https://www.baidu.com/s?wd=ip' 6 7 #不同的代理IP,代理ip的类型必须和请求url的协议头保持一致 8 proxy_list = [ 9 {"http": "112.115.57.20:3128"}, 10 {'http': '121.41.171.223:3128'} 11 ] 12 13 #随机获取代理IP 14 proxy = random.choice(proxy_list) 15 16 page_text = requests.get(url=url,headers=headers,proxies=proxy).text 17 18 with open('ip.html','w',encoding='utf-8') as fp: 19 fp.write(page_text) 20 21 print('over!')
2. 基于requests模块的cookie操作
cookie概念
当用户通过浏览器首次访问一个域名时,访问的web服务器会给客户端发送数据,以保持web服务器与客户端之间的状态保持,这些数据就是cookie。
为什么会有cookie呢?
因为http和https都是短链接,链接成功之后链接马上断开了。服务端是不会保存客户端的相关信息的。所以,服务端和客户端是没有办法建立一个长链接的。为了让服务端长久的记录客户端的状态。才会产生cookie这样一种机制。客户端第一次访问服务端的时候,服务端会给客户端创建一次会话,会给客户端创建一个cookie,用来让服务器端记录客户端相关的状态的。服务器端把cookie创建好之后,cookie不会存在服务器端,会让服务器端发送给客户端,会保存到客户端浏览器本地。一旦存到客户端之后,客户端下次向服务器发请求的时候,就可以携带这个cookie了。服务端就可以收到这个cookie,服务端就会根据这个cookie来判定当前客户端是怎么样的状态。
cookie 使用
- 手动处理:将cookie添加到headers
- 自动处理:使用会话对象requests.Session(),会话对象可以向requests模块一样进行请求的发送。
案例1:雪球网,爬取新闻标题和内容
1 import requests 2 from lxml import etree 3 headers = { 4 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36' 5 } 6 7 # 创建一个会话对象:可以像requests模块一样发起请求。如果请求过程中产生cookie的话,则cookie会被会话自动处理 8 s = requests.Session() 9 first_url = 'https://xueqiu.com/' 10 11 #请求过程中会产生cookie,cookie就会被存储到session对象中,从起始url获取cookie 12 s.get(url=first_url,headers=headers) 13 14 15 url = 'https://xueqiu.com/v4/statuses/public_timeline_by_category.json?since_id=-1&max_id=-1&count=10&category=-1' 16 17 #携带cookie,对url进行请求发送。# 这里不不能用request发送,要用session对象 18 json_obj = s.get(url=url,headers=headers).json() 19 print(json_obj)
案例2:模拟登录古诗文网
请求这个验证码图片的时候,也会产生cookie,模拟登陆的时候需要使用这张图片所对应的cookie,所以直接使用session发送请求。这个案例总共保存了2组cookie , 一组是验证码的,一组是登录信息的。
1 import requests 2 import urllib 3 from lxml import etree 4 headers = { 5 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36' 6 } 7 s = requests.Session() 8 login_url = 'https://so.gushiwen.org/user/login.aspx?from=http://so.gushiwen.org/user/collect.aspx' 9 page_text = requests.get(url=login_url,headers=headers).text 10 tree = etree.HTML(page_text) 11 img_src = 'https://so.gushiwen.org'+tree.xpath('//*[@id="imgCode"]/@src')[0] 12 img_data = s.get(url=img_src,headers=headers).content 13 with open('./img.jpg','wb') as fp: 14 fp.write(img_data) 15 img_text = getCodeDate('bobo328410948','bobo328410948','./img.jpg',1004) 16 17 #模拟登录 18 url = 'https://so.gushiwen.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx' 19 data = { 20 "__VIEWSTATE":"9AsGvh3Je/0pfxId7DYRUi258ayuEG4rrQ1Z3abBgLoDSOeAUatOZOrAIxudqiOauXpR9Zq+dmKJ28+AGjXYHaCZJTTtGgrEemBWI1ed7oS7kpB7Rm/4yma/+9Q=", 21 "__VIEWSTATEGENERATOR":"C93BE1AE", 22 "from":"http://so.gushiwen.org/user/collect.aspx", 23 "email":"[email protected]", 24 "pwd":"*****", 25 "code":img_text, 26 "denglu":"登录", 27 } 28 page_text = s.post(url=url,headers=headers,data=data).text 29 with open('./gushiwen.html','w',encoding='utf-8') as fp: 30 fp.write(page_text)
3. 基于multiprocessing.dummy线程池的数据爬取
案例:爬取梨视频数据。在爬取和持久化存储方面比较耗时,所以两个都需要多线程
1 import requests 2 import re 3 from lxml import etree 4 from multiprocessing.dummy import Pool 5 import random 6 7 pool = Pool(5) # 实例化一个线程池对象 8 9 url = 'https://www.pearvideo.com/category_1' 10 headers = { 11 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36' 12 } 13 page_text = requests.get(url=url,headers=headers).text 14 tree = etree.HTML(page_text) 15 li_list = tree.xpath('//div[@id="listvideoList"]/ul/li') 16 17 video_url_list = [] 18 for li in li_list: 19 detail_url = 'https://www.pearvideo.com/'+li.xpath('./div/a/@href')[0] 20 detail_page = requests.get(url=detail_url,headers=headers).text 21 video_url = re.findall('srcUrl="(.*?)",vdoUrl',detail_page,re.S)[0] 22 video_url_list.append(video_url) 23 24 # pool.map(回调函数,可迭代对象)函数依次执行对象 25 video_data_list = pool.map(getVideoData,video_url_list) # 获取视频 26 27 pool.map(saveVideo,video_data_list) # 持久化存储 28 29 def getVideoData(url): 30 return requests.get(url=url,headers=headers).content 31 32 def saveVideo(data): 33 fileName = str(random.randint(0,5000))+'.mp4' # 因回调函数只能传一个参数,所以没办法再传名字了,只能自己取名 34 with open(fileName,'wb') as fp: 35 fp.write(data) 36 37 38 pool.close() 39 pool.join()