标签:
最近杭州房价涨得好凶,要不要跟风买房,确实是个头疼的问题,不过做点准备总是没坏处的。前段时间我找了一个我爱我家的中介了解了下情况,他提到我爱我家官网,说上面信息的时效性和准确度都不错,可以时常关注一下。本着程序员的天性,一切可以用脚本偷懒的事情就都不要麻烦自己动手了,于是就写了一个脚本,用于监测我爱我家官网的消息变动,有新的房源信息就发短信给自己。
首先分析一下可行性,爬取网站,取得HTML页面的信息当然是没什么难度的,接下来就是从中整理出有用的信息,然后发短信给自己了。
发送短信的服务,搜索了一下有好几家,但很多都是套餐包,最便宜的也要几百块,作为我这种非刚需用户来说有点贵了。挑来挑去,最终我选了阿里大于作为短信发送平台,因为阿里大于是按条数收费的,按需收费,每条4.5分,而且是淘宝账号登录,支付宝付款,也比较方便。
Talk is cheap, show me the code. 先上代码。以之江一号小区为例,如果要搜索其他小区,只要修改url的最后一个字段即可。
wiwj.py文件
1 # -*- coding: utf-8 -*-
2
3 import urllib2
4 import re
5 import sms
6 import logging
7 logging.basicConfig(level=logging.DEBUG,
8 filename=‘log.log‘
9 )
10
11
12 def del_html_mark(content):
13 inner_pattern = re.compile(‘<.*?>‘)
14 return re.sub(inner_pattern, ‘‘, content)
15
16
17 def del_additional_mark(content):
18 inner_pattern = re.compile(‘ ‘)
19 content = re.sub(inner_pattern, ‘‘, content)
20 inner_pattern = re.compile(‘[;\t\n ]‘)
21 content = re.sub(inner_pattern, ‘‘, content)
22 return content
23
24
25 def handle_content(content):
26 content = del_html_mark(content)
27 content = del_additional_mark(content)
28 return content
29
30
31 url = ‘http://hz.5i5j.com/exchange/_%E4%B9%8B%E6%B1%9F%E4%B8%80%E5%8F%B7‘
32 user_agent = ‘Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)‘
33 headers = {‘User-Agent‘: user_agent}
34 html_content = ‘‘
35 logging.info(‘Starting scanning...‘)
36 try:
37 request = urllib2.Request(url, headers=headers)
38 response = urllib2.urlopen(request)
39 html_content = response.read()
40 # print html_content
41 except urllib2.URLError, e:
42 if hasattr(e, "code"):
43 print e.code
44 if hasattr(e, "reason"):
45 print e.reason
46
47 content = html_content.decode(‘utf-8‘)
48 pattern = re.compile(‘<div class="list-info">(.*?)</div>‘, re.S)
49 items = re.findall(pattern, content)
50 for item in items:
51 title_pattern = re.compile(‘<h2><a href=.*?>(.*?)</a></h2>‘)
52 title_list = re.findall(title_pattern, item)
53 title = title_list[0]
54 title = handle_content(title)
55 # print title
56 community_pattern = re.compile(‘<a href=.*? target="_blank"><h3 >(.*?)</h3></a>‘)
57 community_list = re.findall(community_pattern, item)
58 community = community_list[0]
59 community = handle_content(community)
60 # print community
61 detail_pattern = re.compile(‘<li class="font-balck">(.*?)</li>‘)
62 detail_list = re.findall(detail_pattern, item)
63 detail = detail_list[0]
64 detail = handle_content(detail)
65 # print detail
66 price_pattern = re.compile(‘<h3>(.*?)</em></h3>‘)
67 price_list = re.findall(price_pattern, item)
68 price = price_list[0]
69 price = handle_content(price)
70 # print price
71 size_pattern = re.compile(‘<p>(.*?)/.*?</p>‘)
72 size_list = re.findall(size_pattern, item)
73 size = size_list[0]
74 size = handle_content(size)
75 total_msg = {
76 ‘title‘: title.encode(‘utf-8‘),
77 ‘community‘: community.encode(‘utf-8‘),
78 ‘detail‘: detail.encode(‘utf-8‘),
79 ‘price‘: price.encode(‘utf-8‘),
80 ‘size‘: size.encode(‘utf-8‘)
81 }
82 file = open(‘record.log‘, ‘r‘)
83 old_info_list = file.readlines()
84 for old_info in old_info_list:
85 old_info = del_additional_mark(old_info)
86 file.close()
87 is_old_message = False
88 for old_info in old_info_list:
89 if old_info == (total_msg[‘title‘] + ‘\n‘):
90 is_old_message = True
91 break
92 if is_old_message:
93 continue
94 file = open(‘record.log‘, ‘a‘)
95 print total_msg
96 sms.send_msg(total_msg, ‘我的手机号码‘)
97 file.write(total_msg[‘title‘] + ‘\n‘)
98 file.close()
99 logging.info(total_msg[‘title‘])
100 logging.info(total_msg[‘detail‘])
101 logging.info(total_msg[‘community‘])
102 logging.info(total_msg[‘size‘])
103 logging.info(total_msg[‘price‘])
104 logging.info(‘Finished scanning.‘)
105 file.close()
sms.py文件
1 # -*- coding: utf-8 -*-
2
3 import top.api
4
5
6 def send_msg(msg, tel):
7 app_key = "******"
8 secret_key = "******"
9
10 req = top.api.AlibabaAliqinFcSmsNumSendRequest()
11 req.set_app_info(top.appinfo(app_key, secret_key))
12
13 req.extend = ""
14 req.sms_type = "normal"
15 req.sms_free_sign_name = "******"
16 req.sms_param = "{‘position‘:‘" + msg[‘community‘] + "‘,‘temperature‘:‘" + msg[‘size‘] + 17 "‘,‘detail‘:‘" + msg[‘price‘] + "‘}"
18 req.rec_num = tel
19 req.sms_template_code = "******"
20 try :
21 resp = req.getResponse()
22 print (resp)
23 except Exception, e:
24 print (e)
25
26
27 if __name__ == "__main__":
28 send_msg(‘测试文本‘, ‘测试电话号码‘)
wiwj.py是主文件,基本原理是将Python脚本伪装成浏览器,对特定页面进行爬取,然后将获取到的HTML文本信息用正则表达式取出需要的字段,包括房屋总价、面积、单价、描述等。
sms.py文件中接入了阿里大于的SDK top.api,通过这两句引入,然后根据申请的模板信息,设定一些参数
req = top.api.AlibabaAliqinFcSmsNumSendRequest()
req.set_app_info(top.appinfo(app_key, secret_key))
sms.py文件中我申请的模板的信息在这里用******替代了,读者如果需要,可以去申请一个模板。
因为我爱我家官网上的信息是时常变动的,即使是老信息,也可能突然更新一下,显示在最前面,而且网站上并没有房屋位置的详细信息,所以无法直接判定某条刚更新过的信息是不是之前就有的。我采取的判断一条信息是否是老信息的方法是,维护一个log文件,将每次爬取到的房产信息都写在这个log文件中,每次爬取到新的信息,就跟log文件中已有的信息进行对比,如果总价、单价和描述都相同,就认为这是同一个房子,不发送短信提醒。如果不完全相同,说明这就是新房子,发送短信提醒。
补充一句,有读者可能会对这一句感到奇怪
req.sms_param = "{‘position‘:‘" + msg[‘community‘] + "‘,‘temperature‘:‘" + msg[‘size‘] + 17 "‘,‘detail‘:‘" + msg[‘price‘] + "‘}"
这是因为阿里大于的短信发送模板是需要进行审核的,我之前提审了几个模板,其中有房产相关的文字,最终处理结果都是审批不通过,最后只好伪装成发送天气预报信息的短信模板,这样才过了审核。不过阿里大于比较赞的一点是,它会把审核不通过的原因写出来,这样就可以有针对性地进行修改,然后再次提审。
最后,将这些脚本放到我的个人VPS上(树莓派也可以),并设定了crontab定时任务,
*/10 * * * * python ~/Documents/Fang/wiwj.py
每10分钟执行一次,实时度基本可以接受。
就这样,大功告成 XD
标签:
原文地址:http://www.cnblogs.com/istream/p/5940429.html