05 requests模块进阶

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发送请求。这个案例总共保存了2cookie , 一组是验证码的,一组是登录信息的。

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

猜你喜欢

转载自www.cnblogs.com/Summer-skr--blog/p/11402076.html
05