Python爬虫:设置Cookie解决网站拦截并爬取蚂蚁短租
文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。
作者: Eastmount
PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取
http://note.youdao.com/noteshare?id=3054cce4add8a909e784ad934f956cef
我们在编写Python爬虫时,有时会遇到网站拒绝访问等反爬手段,比如这么我们想爬取蚂蚁短租数据,它则会提示“当前访问疑似黑客攻击,已被网站管理员设置为拦截”提示,如下图所示。此时我们需要采用设置Cookie来进行爬取,下面我们进行详细介绍。非常感谢我的学生承峰提供的思想,后浪推前浪啊!
一. 网站分析与爬虫拦截
当我们打开蚂蚁短租搜索贵阳市,反馈如下图所示结果。 我们可以看到短租房信息呈现一定规律分布,如下图所示,这也是我们要爬取的信息。
通过浏览器审查元素,我们可以看到需要爬取每条租房信息都位于<dd></dd>节点下。 在定位房屋名称,如下图所示,位于<div class="room-detail clearfloat"></div>节点下。
接下来我们写个简单的BeautifulSoup进行爬取。
1 # -*- coding: utf-8 -*- 2 import urllib 3 import re 4 from bs4 import BeautifulSoup 5 import codecs 6 7 url = 'http://www.mayi.com/guiyang/?map=no' 8 response=urllib.urlopen(url) 9 contents = response.read() 10 soup = BeautifulSoup(contents, "html.parser") 11 print soup.title 12 print soup 13 #短租房名称 14 for tag in soup.find_all('dd'): 15 for name in tag.find_all(attrs={"class":"room-detail clearfloat"}): 16 fname = name.find('p').get_text() 17 print u'[短租房名称]', fname.replace('\n','').strip()
但很遗憾,报错了,说明蚂蚁金服防范措施还是挺到位的。
二. 设置Cookie的BeautifulSoup爬虫
添加消息头的代码如下所示,这里先给出代码和结果,再教大家如何获取Cookie。
1 # -*- coding: utf-8 -*- 2 import urllib2 3 import re 4 from bs4 import BeautifulSoup 5 6 7 #爬虫函数 8 def gydzf(url): 9 user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36" 10 headers={"User-Agent":user_agent} 11 request=urllib2.Request(url,headers=headers) 12 response=urllib2.urlopen(request) 13 contents = response.read() 14 soup = BeautifulSoup(contents, "html.parser") 15 for tag in soup.find_all('dd'): 16 #短租房名称 17 for name in tag.find_all(attrs={"class":"room-detail clearfloat"}): 18 fname = name.find('p').get_text() 19 print u'[短租房名称]', fname.replace('\n','').strip() 20 #短租房价格 21 for price in tag.find_all(attrs={"class":"moy-b"}): 22 string = price.find('p').get_text() 23 fprice = re.sub("[¥]+".decode("utf8"), "".decode("utf8"),string) 24 fprice = fprice[0:5] 25 print u'[短租房价格]', fprice.replace('\n','').strip() 26 #评分及评论人数 27 for score in name.find('ul'): 28 fscore = name.find('ul').get_text() 29 print u'[短租房评分/评论/居住人数]', fscore.replace('\n','').strip() 30 #网页链接url 31 url_dzf = tag.find(attrs={"target":"_blank"}) 32 urls = url_dzf.attrs['href'] 33 print u'[网页链接]', urls.replace('\n','').strip() 34 urlss = 'http://www.mayi.com' + urls + '' 35 print urlss 36 37 #主函数 38 if __name__ == '__main__': 39 i = 1 40 while i<10: 41 print u'页码', i 42 url = 'http://www.mayi.com/guiyang/' + str(i) + '/?map=no' 43 gydzf(url) 44 i = i+1 45 else: 46 print u"结束"
输出结果如下图所示:
1 页码 1 2 [短租房名称] 大唐东原财富广场--城市简约复式民宿 3 [短租房价格] 298 4 [短租房评分/评论/居住人数] 5.0分·5条评论·二居·可住3人 5 [网页链接] /room/851634765 6 http://www.mayi.com/room/851634765 7 [短租房名称] 大唐东原财富广场--清新柠檬复式民宿 8 [短租房价格] 568 9 [短租房评分/评论/居住人数] 2条评论·三居·可住6人 10 [网页链接] /room/851634467 11 http://www.mayi.com/room/851634467 12 13 ... 14 15 页码 9 16 [短租房名称] 【高铁北站公园旁】美式风情+超大舒适安逸 17 [短租房价格] 366 18 [短租房评分/评论/居住人数] 3条评论·二居·可住5人 19 [网页链接] /room/851018852 20 http://www.mayi.com/room/851018852 21 [短租房名称] 大营坡(中大国际购物中心附近)北欧小清新三室 22 [短租房价格] 298 23 [短租房评分/评论/居住人数] 三居·可住6人 24 [网页链接] /room/851647045 25 http://www.mayi.com/room/851647045
接下来我们想获取详细信息
这里作者主要是提供分析Cookie的方法,使用浏览器打开网页,右键“检查”,然后再刷新网页。在“NetWork”中找到网页并点击,在弹出来的Headers中就隐藏这这些信息。
最常见的两个参数是Cookie和User-Agent,如下图所示:
然后在Python代码中设置这些参数,再调用Urllib2.Request()提交请求即可,核心代码如下:
1 user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/61.0.3163.100 Safari/537.36" 2 cookie="mediav=%7B%22eid%22%3A%22387123...b3574ef2-21b9-11e8-b39c-1bc4029c43b8" 3 headers={"User-Agent":user_agent,"Cookie":cookie} 4 request=urllib2.Request(url,headers=headers) 5 response=urllib2.urlopen(request) 6 contents = response.read() 7 soup = BeautifulSoup(contents, "html.parser") 8 for tag1 in soup.find_all(attrs={"class":"main"}):
注意,每小时Cookie会更新一次,我们需要手动修改Cookie值即可,就是上面代码的cookie变量和user_agent变量。完整代码如下所示:
1 import urllib2 2 import re 3 from bs4 import BeautifulSoup 4 import codecs 5 import csv 6 7 8 c = open("ycf.csv","wb") #write 写 9 c.write(codecs.BOM_UTF8) 10 writer = csv.writer(c) 11 writer.writerow(["短租房名称","地址","价格","评分","可住人数","人均价格"]) 12 13 14 #爬取详细信息 15 def getInfo(url,fname,fprice,fscore,users): 16 #通过浏览器开发者模式查看访问使用的user_agent及cookie设置访问头(headers)避免反爬虫,且每隔一段时间运行要根据开发者中的cookie更改代码中的cookie 17 user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36" 18 cookie="mediav=%7B%22eid%22%3A%22387123%22eb7; mayi_uuid=1582009990674274976491; sid=42200298656434922.85.130.130" 19 headers={"User-Agent":user_agent,"Cookie":cookie} 20 request=urllib2.Request(url,headers=headers) 21 response=urllib2.urlopen(request) 22 contents = response.read() 23 soup = BeautifulSoup(contents, "html.parser") 24 #短租房地址 25 for tag1 in soup.find_all(attrs={"class":"main"}): 26 print u'短租房地址:' 27 for tag2 in tag1.find_all(attrs={"class":"desWord"}): 28 address = tag2.find('p').get_text() 29 print address 30 #可住人数 31 print u'可住人数:' 32 for tag4 in tag1.find_all(attrs={"class":"w258"}): 33 yy = tag4.find('span').get_text() 34 print yy 35 fname = fname.encode("utf-8") 36 address = address.encode("utf-8") 37 fprice = fprice.encode("utf-8") 38 fscore = fscore.encode("utf-8") 39 fpeople = yy[2:3].encode("utf-8") 40 ones = int(float(fprice))/int(float(fpeople)) 41 #存储至本地 42 writer.writerow([fname,address,fprice,fscore,fpeople,ones]) 43 44 45 #爬虫函数 46 def gydzf(url): 47 user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36" 48 headers={"User-Agent":user_agent} 49 request=urllib2.Request(url,headers=headers) 50 response=urllib2.urlopen(request) 51 contents = response.read() 52 soup = BeautifulSoup(contents, "html.parser") 53 for tag in soup.find_all('dd'): 54 #短租房名称 55 for name in tag.find_all(attrs={"class":"room-detail clearfloat"}): 56 fname = name.find('p').get_text() 57 print u'[短租房名称]', fname.replace('\n','').strip() 58 #短租房价格 59 for price in tag.find_all(attrs={"class":"moy-b"}): 60 string = price.find('p').get_text() 61 fprice = re.sub("[¥]+".decode("utf8"), "".decode("utf8"),string) 62 fprice = fprice[0:5] 63 print u'[短租房价格]', fprice.replace('\n','').strip() 64 #评分及评论人数 65 for score in name.find('ul'): 66 fscore = name.find('ul').get_text() 67 print u'[短租房评分/评论/居住人数]', fscore.replace('\n','').strip() 68 #网页链接url 69 url_dzf = tag.find(attrs={"target":"_blank"}) 70 urls = url_dzf.attrs['href'] 71 print u'[网页链接]', urls.replace('\n','').strip() 72 urlss = 'http://www.mayi.com' + urls + '' 73 print urlss 74 getInfo(urlss,fname,fprice,fscore,user_agent) 75 76 #主函数 77 if __name__ == '__main__': 78 i = 0 79 while i<33: 80 print u'页码', (i+1) 81 if(i==0): 82 url = 'http://www.mayi.com/guiyang/?map=no' 83 if(i>0): 84 num = i+2 #除了第一页是空的,第二页开始按2顺序递增 85 url = 'http://www.mayi.com/guiyang/' + str(num) + '/?map=no' 86 gydzf(url) 87 i=i+1 88 89 c.close()
输出结果如下,存储本地CSV文件: