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":"xxx@qq.com",
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()