爬取安居客住房信息

本来这两天是打算继续学习数据挖掘的,但是在偶然的机会下突然想去爬取下安居客的房源信息,写的程序代码比较乱,基本没有什么健壮性,函数各个功能也没有分开。感觉对于爬虫来说数据处理是一大重要的问题,本来我已经把大的方向写好了,但是总是报一些细节的错误,就是在哪里各种的调试,花费了好长时间。最后的爬取的结果如下面的图所示。 主要是整合的数据稍微的困难一点,其他的下面就直接先上代码,这个代码写的比较差,也不够优美,实在是不想在改了,调优花费的时间比写爬虫还要多。

import requests

from bs4 import BeautifulSoup

import re

from redis import StrictRedis

import xlrd

import xlwt

from xlutils.copy import copy

red = StrictRedis(host='localhost', port=6379, db=0)

s=requests.Session()#自动处理cookies,没有就无法访问详情页

redis1 = StrictRedis(host='localhost', port=6379, db=0)

global counts

counts=0#声明全局变量,用来统计爬取多少条的

def get_one_page(page):

url='https://shenzhen.anjuke.com/sale/p'+str(page)#初始的url,爬虫从这开始

header={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0',

}

r=s.get(url=url,headers=header)

url_info = re.findall('https:.*?time=\d{1,}',r.text)

url_info_list=[]

for info in url_info:

# redis1.rpush('url_list', info)#这里一开始时打算用redis的但是总是报错就算了,数据库比列表性能好。

url_info_list.append(info)#获取详情页url存在列表中

#print(url_info_list)

soup=BeautifulSoup(r.text,'lxml')

#print(soup)

house_info=soup.find_all('div',class_='house-title')

house_details=soup.find_all('div',class_='details-item')

house_price=soup.find_all('div',class_='pro-price')#获取详情页的房子价格等信息

phone_list=[]#电话列表,用于存放电话信息

contact_list=[]#联系人列表,用于存放联系人信息

for url in url_info_list:

# while redis1.lpop('url_list'):

#url = redis1.lpop('url_list')#这里一开始时打算用redis的但是总是报错就算了,数据库比列表性能好。

r = s.get(url=url, headers=header)

soup1 = BeautifulSoup(r.text, 'lxml')

try:###这里总是报错添加个异常处理

contact = soup1.find('div', class_='brokercard-name').text[0:3]

if contact:

contact_list.append(contact)

else:

contact_list.append('佚名')#如果抓不到联系人信息,就补全防止异常

except:

pass

if re.findall("im_broker_id = '(\d{4,})'", r.text)[0]:#这里也总是异常,添加个判断处理下

broker_id = re.findall("im_broker_id = '(\d{4,})'", r.text)[0]

else:

continue

prop_id1 = re.findall("house_id:'.*?'", r.text)

prop_id = re.findall("(\d{4,})", prop_id1[0])[0]

token = re.findall("token: '(.*?)',", r.text)[0]

prop_city_id = re.findall("prop_city_id: '(\d{1,})',", r.text)[0]

house_type = re.findall("house_type: '(\d{1,})'", r.text)[0]

url1 = r'https://shenzhen.anjuke.com/v3/ajax/broker/phone/?'

base = 'broker_id=' + broker_id + '&token=' + token + '&prop_id=' + prop_id + '&prop_city_id=' + prop_city_id + '&house_type=' + house_type + '&captcha='

url2 = url1 + base #获取到broker_id , token等信息对其做拼接形成新的url

res = s.get(url=url2, headers=header)#请求获得电话信息

# print(res.text)

last_info = re.findall('''"val":"(.*?)"''', res.text)

phone_list.append(last_info[0].replace(' ',''))

global counts

for (info1,info2,info3,info4,info5)in zip(house_info,house_details,house_price,contact_list,phone_list):

#for i in range(len(phone_list)):#遍历每个列表,将每个列表对应的第i个信息加入列表list_info。并写入excel。

list_info=[]

info_href=info1.a.attrs['href']

#print(type(info1))

info=info1.text.strip()

inf=info2.text.strip()

house_title=info.strip()

house_detail=inf.strip()

price=re.findall(r'(\d{2,}.)',info3.text)

house_price=price[0]

house_price_averge=price[1]

print('xxxxxxxxxxxxxxxxxxxxxxx')

counts+=1

print(counts)

list_info.append(house_title)

list_info.append(house_detail)

list_info.append(house_price.replace('万',''))

list_info.append(house_price_averge.replace('元',''))

list_info.append(info4.strip())

list_info.append(info5)

write_one_excel_xls_append(r'C:\Users\ASUS\Desktop\test_worm\details.xls', list_info)

def get_manypage(page):

for i in range(page):

get_one_page(i)

#写入excel表格

def write_excel_xls(path, sheet_name, value):

index = len(value) # 获取需要写入数据的行数

workbook = xlwt.Workbook() # 新建一个工作簿

sheet = workbook.add_sheet(sheet_name) # 在工作簿中新建一个表格

for i in range(0, index):

for j in range(0, len(value[i])):

sheet.write(i, j, value[i][j]) # 像表格中写入数据(对应的行和列)

workbook.save(path) # 保存工作簿

print("xls创建成功")

#行数据写入

def write_one_excel_xls_append(path, value):

# 获取需要写入数据的行数

workbook = xlrd.open_workbook(path) # 打开工作簿

sheets = workbook.sheet_names() # 获取工作簿中的所有表格

worksheet = workbook.sheet_by_name(sheets[0]) # 获取工作簿中所有表格中的的第一个表格

rows_old = worksheet.nrows # 获取表格中已存在的数据的行数

new_workbook = copy(workbook) # 将xlrd对象拷贝转化为xlwt对象

new_worksheet = new_workbook.get_sheet(0) # 获取转化后工作簿中的第一个表格

for j in range(0, len(value)):

new_worksheet.write(rows_old, j, value[j]) # 追加写入数据,注意是从i+rows_old行开始写入

new_workbook.save(path) # 保存工作簿

global count

count+=1

print("xls格式表格追加第"+str(count)+"数据成功!")

if __name__ == '__main__':

info = [['标题', '详细信息', '总价(万)', '均价(m^2)','联系人','电话'], ]

write_excel_xls(r'C:\Users\ASUS\Desktop\test_worm\details.xls', 'work1', info)

get_manypage(2)

说一下爬虫的全部的步骤吧,起始页面url是https://shenzhen.anjuke.com/sale/p1,当然这里的p1代表的是页面可以增加,每页应该是60个信息,初始页面如下图所示,

在初始页面有每一个详情页的url这里用以下的函数获取。本来打算用redis数据库的这样速度会快很多,但总是报错,就算了。

r=s.get(url=url,headers=header)

url_info = re.findall('https:.*?time=\d{1,}',r.text)#获取详情页的url

url_info_list=[]

for info in url_info:

# redis1.rpush('url_list', info)

url_info_list.append(info)

print(url_info_list)

函数将url获得到并保存在url_info_list列表中。

详情页的url获得到之后就进行再一次的请求,就可以对数据进行提取了,这里提取了标题,详细信息,均价和总价,联系人,电话几个信息,前五个没什么好说的,直接在详情页用BeautifulSoup提取出来就就好了。

soup=BeautifulSoup(r.text,'lxml')

#print(soup)

house_info=soup.find_all('div',class_='house-title')

house_details=soup.find_all('div',class_='details-item')

house_price=soup.find_all('div',class_='pro-price')

直接提取出来相应的信息就好了

最后一个电话信息需是一个xhr类型的请求,需要在在详情页请求一遍才能获得。

找到这个请求发现请求的url为https://shenzhen.anjuke.com/v3/ajax/broker/phone/?broker_id=3982970&token=00bd244b85e99fa171ad7b429ebd11cc&prop_id=1594723649&prop_city_id=13&house_type=1&captcha=里面有几个参数需要在详情页获取,在这里我只是对这个请求的url做了简单的拼接再对服务器请求一遍获得电话信息。

if re.findall("im_broker_id = '(\d{4,})'", r.text)[0]:

broker_id = re.findall("im_broker_id = '(\d{4,})'", r.text)[0]

else:

continue

prop_id1 = re.findall("house_id:'.*?'", r.text)

prop_id = re.findall("(\d{4,})", prop_id1[0])[0]

token = re.findall("token: '(.*?)',", r.text)[0]

prop_city_id = re.findall("prop_city_id: '(\d{1,})',", r.text)[0]

house_type = re.findall("house_type: '(\d{1,})'", r.text)[0]

url1 = r'https://shenzhen.anjuke.com/v3/ajax/broker/phone/?'

base = 'broker_id=' + broker_id + '&token=' + token + '&prop_id=' + prop_id + '&prop_city_id=' + prop_city_id + '&house_type=' + house_type + '&captcha='

url2 = url1 + base

# 获取broker_id,token,prop_id,prop_city_id,house_type,等信息,

然后拼接成一个新的url2,再对其进行请求一次。就可以获得电话信息的json字符串。

做完这戏之后对获得的6个信息进行遍历放入列表中,并将其写入excel中。

for (info1,info2,info3,info4,info5)in zip(house_info,house_details,house_price,contact_list,phone_list):

#for i in range(len(phone_list)):

list_info=[]

info_href=info1.a.attrs['href']

#print(type(info1))

info=info1.text.strip()

inf=info2.text.strip()

house_title=info.strip()

house_detail=inf.strip()

price=re.findall(r'(\d{2,}.)',info3.text)

house_price=price[0]

house_price_averge=price[1]

print('xxxxxxxxxxxxxxxxxxxxxxx')

counts+=1

print(counts)

list_info.append(house_title)

list_info.append(house_detail)

list_info.append(house_price.replace('万',''))

list_info.append(house_price_averge.replace('元',''))

list_info.append(info4.strip())

list_info.append(info5)

write_one_excel_xls_append(r'C:\Users\ASUS\Desktop\test_worm\details.xls', list_info)

感觉自己写的代码好乱,但是实在是不想再改了,反正也是自己写着玩的,功能都实现了。优化比自己在重新写一遍还要花费时间。而且自己的水平也就这样在改估计也改的不会太好的。