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