最近在做一些项目,需要使用爬虫进行链家网二手房的数据爬取。本人已经使用过request和selenium进行爬取,但是都失败了。总感觉缺了点什么,就是用bs4进行链家二手房数据爬取了
效果图:
下面也不废话了,直接上代码
import time
import random
import pandas as pd
import requests
from bs4 import BeautifulSoup
regions = ['gulou', 'jianye','qinhuai', 'xuanwu', 'qixia', 'pukou', 'liuhe', 'lishui', 'jurongshi']
ua = random.choice([
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15",
"Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1"
])
# 定义一些随机的请求间隔时间
request_intervals = [0.5,1,1.2,1.5] # 单位:秒
a = []
last_save_time = time.time() # 记录上次保存的时间
def get_info(url, region): # 新增 region 参数
global last_save_time
# 随机选择一个请求间隔时间
interval = random.choice(request_intervals)
time.sleep(interval) # 增加随机等待时间
wb_data = requests.get(url, headers={'User-Agent':ua})
# 处理可能的 HTTP 错误状态码
if wb_data.status_code!= 200:
print(f"请求 {url} 失败,状态码: {wb_data.status_code}")
return
# 爬取整个网页
soup = BeautifulSoup(wb_data.text, 'lxml')
# 网页单个元素
title = soup.select('div.title > a')
ranks = soup.select('div.totalPrice.totalPrice2 > span')
# 新增:提取房屋信息
house_info_elements = soup.select('div.address div.houseInfo')
location = soup.select('div.flood > div > a')
area = soup.select('div.flood > div > a:nth-child(3)')
fllowInfo = soup.select('div.followInfo')
tags_div = soup.select('div.tag') # 提取包含 tags 的 div
# 处理 tags
tags = []
if tags_div: # 增加判断,若 tags_div 不为空再进行处理
for tag_span in tags_div[0].find_all('span'): # 假设只有一个这样的 div
tags.append(tag_span.text)
# 存入进列表
for title_item, rank, house_info_element, location_item, area_item, fllowInfo_item in zip(title, ranks, house_info_elements, location, area, fllowInfo):
# 从房屋信息元素中提取详细信息
house_info_text = house_info_element.get_text().strip()
house_info_parts = house_info_text.split(' | ')
room_count = house_info_parts[0] if len(house_info_parts) > 0 else ''
area_size = house_info_parts[1] if len(house_info_parts) > 1 else ''
orientation = house_info_parts[2] if len(house_info_parts) > 2 else ''
decoration = house_info_parts[3] if len(house_info_parts) > 3 else ''
floor_level = house_info_parts[4] if len(house_info_parts) > 4 else ''
building_type = house_info_parts[5] if len(house_info_parts) > 5 else ''
data = {
'标题': title_item.get_text().strip(),
'价格': rank.get_text().strip(),
'室': room_count,
'面积': area_size,
'朝向': orientation,
'装修': decoration,
'楼层': floor_level,
'楼房类型': building_type,
'位置': location_item.get_text().strip() + '-' + area_item.get_text().strip(),
'关注': fllowInfo_item.get_text().strip().split('/')[0],
'距今发布日期': fllowInfo_item.get_text().strip().split('/')[1],
'地区': region, # 新增地区列
'标签': ', '.join(tags) # 以逗号分隔的标签字符串
}
a.append(data)
print(data)
current_time = time.time() # 获取当前时间
if current_time - last_save_time >= 10: # 如果距离上次保存超过 10 秒
df_out = pd.DataFrame(a, columns=['标题', '价格', '室', '面积', '朝向', '装修', '楼层', '楼房类型', '位置', '关注', '距今发布日期', '地区', '标签'])
df_out.to_excel('南京房产信息2.xlsx')
last_save_time = current_time # 更新上次保存时间
if __name__ == '__main__':
# 初始化 urls 列表
urls = []
for re in regions:
url1 = 'https://nj.lianjia.com/ershoufang/'+re+'/pg{}'
# 为每个区域生成相应的页面 URL 并添加到 urls 列表
for i in range(1,101):
urls.append((url1.format(i), re)) # 存储 URL 和对应的地区
for url, region in urls: # 同时获取 URL 和地区
get_info(url, region)
# 最后再保存一次
df_out = pd.DataFrame(a, columns=['标题', '价格', '室', '面积', '朝向', '装修', '楼层', '楼房类型', '位置', '关注', '距今发布日期', '地区', '标签'])
df_out.to_excel('南京房产信息2.xlsx')