代码功能简述:基于Python爬取安居客小区平均房价数据,网址:https://shantou.anjuke.com/community/p40/。获取到小区名称后,利用百度地图API查询其地理坐标。最后需要得到的是城市名、小区名称、经纬度、平均房价。
安居客网站页面如上图,只需获取红框内信息。
完整代码如下:
# -*- coding:utf-8 -*- #这个爬虫是获取安居客小区数据(需要header) import requests from bs4 import BeautifulSoup from urllib2 import urlopen, quote import json import sys import time from xpinyin import Pinyin #导入拼音模块 reload(sys) sys.setdefaultencoding("utf-8") class ajkxq: #创建一个类,类中有两个函数,分别是获取小区信息的getInfo()和得到小区名称后查询其经纬度的getlnglat(),其中getInfo()会调用getlnglat()函数
def getlnglat(self,address): """根据传入地名参数获取经纬度""" url = 'http://api.map.baidu.com/geocoder/v2/' output = 'json' #输出结果可以是json也可以是其他类型 ak = '你自己的密钥' add = quote(str(address))#有时候quote会出错KeyError,要先把quote里面转成字符串类型 uri = url + '?' + 'address=' + add + '&output=' + output + '&ak=' + ak
#构建百度地图API查询需要的uri,uri与URL的区别见:https://www.zhihu.com/question/21950864
#下面这块代码是为了防止因为请求次数过多而产生的错误:urllib2.URLError: <urlopen error [Errno 10060] >
#如果出现该错误,就让程序暂停10秒(time.sleep(10)),继续重新获取该小区的坐标。
#timeout=30是防止因为网络原因出现延迟错误
maxNum=5 for tries in range(maxNum): try: req = urlopen(uri,timeout=30)#设置timeout30秒,防止百度屏蔽,如果被屏蔽就等30秒 except: if tries < (maxNum - 1): time.sleep(10) continue else: print("Has tried %d times, all failed!", maxNum) break res = req.read().decode() temp = json.loads(res) lat = temp['result']['location']['lat'] lng = temp['result']['location']['lng'] return lat, lng
#获取小区信息的函数 def getInfo(self, page, fh, city, citypy): url = 'https://'+citypy+'.anjuke.com/community/p' + str(page)+'/' headers = { #由于安居客网站的反爬虫,这里必须要设置header 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.8', 'Referer': 'https: // wuhan.anjuke.com / sale /?from=navigation', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36' } response = requests.get(url, headers=headers,timeout=30)
#以下是解析网页的过程 bs = BeautifulSoup(response.text, 'html.parser') lis = bs.find_all('div', class_='li-itemmod') for li in lis: infos = li.find_all('div', class_='li-info') for info in infos: titles = info.find_all('h3') for title in titles: strTitle = title.get_text() print city,page,strTitle li_sides = li.find_all('div', class_='li-side') strPrice = '暂无均价' for li_side in li_sides: ps = li_side.find_all('p') for p in ps: strongs=p.find_all('strong') for price in strongs: strPrice = price.get_text() print strPrice address = city + strTitle # 在前面加上城市变量,限定查询城市 try: lat, lng = test.getlnglat(address) print lat, lng fh.write(city.strip()+','+strTitle.strip() + ',' + str(lat).strip() + ',' + str(lng).strip() +','+ strPrice.strip() + '\n') # strip()是去掉每行后面的换行符,只有str类型才能用strip() except KeyError: # 处理未知异常 print("Get AError") if __name__ == '__main__': print "开始爬数据,请稍等..." start_time = time.time() tup1 = [ #设置元组,循环取元组中的元素 '广州','深圳', '佛山', '东莞', '珠海', '中山', '惠州', '肇庆', '江门', '清远', '汕头','梅州', '河源', '揭阳', '潮州', '汕尾', '韶关', '阳江', '茂名', '湛江', '云浮' ]; for i in tup1: city = str(i)#构建拼音,这样每次就只要改这里的城市名就可以了 city = unicode(city, 'utf-8') citypy = Pinyin() #实例化拼音模块的函数 citypy=str(citypy.get_pinyin(city, '')) #还有其他转换拼音的方法,比如在两个字之间加符号等 print citypy stradd='C://Users//Administrator//PycharmProjects//···//guangdong.txt' fh = open(stradd, "a") #输入的文件编码格式必须要与上面type=sys.setdefaultencoding( "utf-8" )一致,即也必须是utf-8 for page in range(1, 101): test=ajkxq()#实例化对象 test.getInfo(page, fh, city, citypy)#方法必须由实例调用 fh.close() #time.sleep(3)#爬完一个城市后暂停3秒 end_time = time.time() print "数据爬取完毕,用时%.2f秒" % (end_time - start_time)