提前准备
- Chrome 浏览器 查看版本号
- chromedriver 查看版本号,需要和浏览器版本号一致
- selenium 地址 通过
pip3 install selenium
安装 - Python3 环境 自行安装。 windows 下载好安装包一路下一步,记得勾中添加环境变量
使用
原理
- selenium 控制 chromedriver 来驱动 Chrome 浏览器
# 引入 webdriver
from selenium import webdriver
# 保存 chromedriver 路径
PATH = 'D:\softwares\chromedriver.exe'
# 接收 webdriver 驱动
driver = webdriver.Chrome(PATH)
# 获取目标地址
driver.get('目标地址')
# 通过 xpath 获取目标文本
total_nums = driver.find_element_by_xpath('//*[@id="content"]/div[1]/div[2]/h2/span')
# 打印爬取目标的文本内容
print(total_nums.text)
# 退出驱动 节省内存
driver.quit()
爬取大量数据思路
- 查看目标网站信息
- 分析
- 总数据 十五万多
- 最多100 个分页,每页最多 30 数据,一次最多只能爬取 3000
- 处理
- 细分查询条件
- 按照位置细分
- 按照位置细分查看
- /heping/
-/nankai/ - 。。。
- /ninghe/
- 后面所有位置在最后的路径上替换对应位置的拼音
- /heping/
- 搜索数据仍多余 3000 条
- 按照位置细分查看
- 在位置细分的基础上再增加搜索条件
- 按售价细分
- /heping/p1/
- /heping/p2/
- 。。。
- /heping/p7/
- 按售价在 url 末尾增加 p1 - p7
- 按售价细分
- 在以上基础下发现还有总数居多余 3000 的情况
- 按房型细分
- /jinnan/l1p1/
- /jinnan/l2p1/
- 。。。
- /jinnan/l6p1/
- 房型 l1 -l6
- 按房型细分
- 如果再有超过 3000 条数据,继续以此思路往下查找,此处不做过多拆解
- 按照位置细分
- 分页查询
- 每一页不同的显示规律,最多到 100页
- /jinnan/l1l6p7/
- /jinnan/pg2l1l6p7/
- /jinnan/pg3l1l6p7/
- 。。。
- 分页 pg1 - pg100
- 每一页不同的显示规律,最多到 100页
- 具体详情页查询
- /jinnan/l1l6p7/
- 有 26 条数据
- 每条数据的标题都带着具体的详情页 url
- /101113895984.html
- /101113405120.html
- 。。。
- 获取每一页的所有数据的详情页,即可获得所有房源的具体信息
- /jinnan/l1l6p7/
- 最终信息查询
- 遍历所有详情页,去获取想要保存的数据
- 细分查询条件
- 分析
- 结果处理
- 分析完毕,开始目标
代码演示
import time
from selenium import webdriver
from lxml import etree
# 大量数据演示
city_url = '目标地址'
PATH = 'D:\softwares\chromedriver.exe'
driver = webdriver.Chrome(PATH)
# 获取具体位置的 url
def get_locate_url():
range_urls = {}
driver.get(city_url)
html = driver.page_source
selector = etree.HTML(html)
for i in range(0, 19):
a_href = str(selector.xpath('/html/body/div[3]/div/div[1]/dl[2]/dd/div[1]/div/a[' + str(i + 1) + ']/@href')[0])
a_name = str(selector.xpath('/html/body/div[3]/div/div[1]/dl[2]/dd/div[1]/div/a[' + str(i + 1) + ']/text()')[0])
range_url = 'https://tj.lianjia.com' + a_href
range_urls[a_name] = range_url
return range_urls
# 获取分条件查找的 url
def get_locate_detail_url():
range_urls = get_locate_url()
range_price_urls = {}
for key in range_urls:
range_url = range_urls[key]
part_range_price_url = []
total_urls = []
for i in range(1, 7):
range_price_url = range_url + 'l' + str(i)
part_range_price_url.append(range_price_url)
for i in part_range_price_url:
for j in range(1, 8):
range_price_url = i + 'p' + str(j)
total_urls.append(range_price_url)
range_price_urls[key] = total_urls
return range_price_urls
# 获取分页详情
# 爬取完全部需要一定时间 展示下即可
def get_page_url():
locate_detail_url = get_locate_detail_url()
total_urls = []
for key in locate_detail_url:
locate_detail_urls = locate_detail_url[key]
for url in locate_detail_urls:
driver.get(url)
# 等待资源加载完成
time.sleep(2)
html = driver.page_source
selector = etree.HTML(html)
# 获取每一页有多少数据
house_nums = int(selector.xpath('//*[@id="content"]/div[1]/div[2]/h2/span/text()')[0])
# 借助 python 整数类型特性
# 每页最多 30 条
# 如果取余为0 说明数据刚好够每页30条
# 如果余数不为0 说明末尾页数据不足30 整体页数要 + 1
yushu = house_nums % 30
if yushu == 0:
page_size = int(house_nums / 30)
else:
page_size = int(house_nums / 30) + 1
print('数据量' + str(house_nums), '余数' + str(yushu), '商' + str(int(house_nums / 30)), '分页数' + str(page_size))
for i in range(0, page_size):
if i == 0:
last_url = url
else:
split_url = url.split('/')
url_detail_search = split_url[5]
last_url = url.replace(url_detail_search, 'pg' + str(i + 1) + url_detail_search)
print(last_url)
total_urls.append(last_url)
return total_urls
# 模拟数据
# 获取具体详情页
# 模拟获取 total_urls
def get_detail_urls():
# total_urls = get_page_url()
total_urls = ['目标地址']
all_details = []
for url in total_urls:
driver.get(url)
time.sleep(2)
html = driver.page_source
selector = etree.HTML(html)
for i in range(0, 30):
try:
# 数据量超过能爬到的数量就会报错
# 报错即跳出循环读取下一页数据
final_url = selector.xpath('//*[@id="content"]/div[1]/ul/li[' + str(i + 1) + ']/div[1]/div[1]/a/@href')[0]
print(final_url)
all_details.append(final_url)
except Exception:
print('没有这么多页数据,跳出结束循环')
break
return all_details
# 获取详细信息
def get_detail_info():
detail_urls = get_detail_urls()
all_details = []
for url in detail_urls:
driver.get(url)
time.sleep(2)
html = driver.page_source
selector = etree.HTML(html)
total_price = selector.xpath('//*[@class="total"]/text()')[0]
unit_price = selector.xpath('//*[@class="unitPriceValue"]/text()')[0]
apartment_name = selector.xpath('//*[@class="communityName"]/a[1]/text()')[0]
range_area = selector.xpath('//*[@class="info"]/a[2]/text()')[0]
print(total_price, unit_price, apartment_name, range_area)
all_details.append({'total_price': total_price, 'unit_price': unit_price, 'apartment_name': apartment_name,
'range_area': range_area})
driver.quit()
return all_details