文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。
作者: 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文件:
