项目需要Python3.6+、requests库、BeautifulSoup4库、re库,适合爬虫初学者阅读。
首先请安装项目所需的第三方库:requests、BeautifulSoup4,请在终端中输入如下命令:
pip install requests BeautifulSoup4
第三方库简介
requests库是一个简洁而强大的Python第三方库,使得发送HTTP请求变得轻松。它已成为众多开发者首选的HTTP库之一,广泛应用于Web开发、爬虫、API调用等场景。不论是初学者还是有经验的开发者,都可以轻松上手使用requests库来处理HTTP请求。
BeautifulSoup4库是一个用于解析HTML和XML文档的库。它提供了一种简单而灵活的方式来从网页中提取数据,特别适用于爬虫和数据抓取任务。
re库 是 Python 中用于处理正则表达式的第三方库。它提供了丰富的函数和方法,用于匹配、替换、分割和提取字符串。re 库在文本操作中具有广泛的应用,为开发者提供了强大的工具来处理各种复杂的字符串操作。
项目实现效果
目标:用户从终端输入要查询的城市代码,然后向链家服务器发送请求,最后接收响应的数据。
思路分析
为了了解网页上的标题、价格、地址等内容,请访问下方链接并打开F12调试模式。如图:上海二手房房源_上海二手房出售|买卖|交易信息(上海链家) (lianjia.com)
切换到选项卡“元素”,您就可以看到当前网站上的源码。如果您使用的Microsoft Edge浏览器,您可以按下Ctr+Shift+C进入选择性检查模式,将鼠标移到标题下面的地址上,再按下鼠标左键,右侧的调试信息就会自动定位到该元素对应的源码位置,如图:
可以看到,已经定位到了一行代码:<div class="positionInfo">,可知,positionInfo表示着该房源的地址,我们后续将通过此元素访问房源的地址。
同理,获取房源单价的元素,如下图:
由定位可知,代表每平米单价的元素为unitPrice
代码实现
from bs4 import BeautifulSoup #1
import requests
import re
print('-----二手房价格查询系统-----') #2
city = input("请输入城市代码(例如上海sh、北京bj): ")
url = "https://%s.lianjia.com/ershoufang/"%(city) #3
try: #4
response = requests.get(url)
data = response.text
soup = BeautifulSoup(data, "html.parser")
price_elements = soup.find_all(class_="unitPrice")
positions = soup.find_all(class_="positionInfo")
title = re.findall('<title>(.+?)</title>', response.text) #5
print(title[0])
pos = [] #6
pr_ele = []
for pos_n in positions:
p = pos_n.text
pos.append(p.replace(" ", ""))
for element in price_elements:
price = element.text
pr_ele.append(price)
value = 0 #7
for p in pos:
print(p, pr_ele[value])
value = value + 1
except requests.exceptions.ConnectionError:
print('暂无查询结果')
在1处,我们导入了此项目需要的三个第三方库。
在2处,系统将打印系统名,并且向用户请求键入城市代码。
在3处,我们定义了url变量,其中使用占位符%s将刚刚用户输入的城市代码插入到url中以补全url。
Python中所有占位符及其解释:
🟢
%s:字符串占位符
e.g.:
"Hello, %s!"%(name)解释:%s表示将后面的变量或值格式化为字符串,并插入到占位符的位置。
🟢
%d:整数占位符
e.g.:"The answer is %d."%(num)
解释:
%d
表示将后面的变量或值格式化为整数,并插入到占位符的位置。
🟢%f
:浮点数占位符
e.g.:
"The value is %.2f." %(value)
解释:
%f
表示将后面的变量或值格式化为浮点数,并插入到占位符的位置。.2f
表示保留两位小数。
🟢%r
:原始字符串占位符
e.g.:
"The string is %r." %(string)
解释:
%r
表示将后面的变量或值格式化为原始字符串,并插入到占位符的位置。原始字符串会包含引号和转义符等特殊字符。
🟢{} + format()
:格式化字符串方法
e.g.:
"My name is {} and I am {} years old.".format(name, age)
解释:
{}
表示占位符的位置,format()
方法用于将后面的变量或值依次插入到占位符的位置。
🟢
f-strings:格式化字符串字面值
e.g.:
f"My name is {name} and I am {age} years old."
解释:以字母f开头的字符串,可以在字符串中直接使用花括号
{}
来插入变量或表达式的值。
在4处,我们加上了一个try-except-语句,防止在用户输入错误信息或查询出错时抛出错误。
在5处,我们通过一个正则表达式获取这是哪个城市的二手房信息,原理如下:
通过查看网站源码,我们便可以发现这一行代码:<title>上海二手房房源_上海二手房出售|买卖|交易信息(上海链家)</title>,其中就包含了当前查询的城市信息,该信息在两个<title></title>之间,因此,我们可以使用正则表达式自动获取这其中的内容。该句语法如下:
title = re.findall('<title>(.+?)</title>', response.text)
正则表达式(.+?)可以提取指定位置的字符,e.g.一个字符串“a123456789b”,如果我们想提取ab之间的数字,可以使用findall方法配合正则表达式,该方法返回的文本类型为list。
在6处,我们定义了两个空列表,分别存储房源的地址与单价。接下来,我们将爬取到的房源信息加入到这两个列表中。在此,我们使用了for遍历列表,因为每一次爬取的信息为一个列表,我们将这个列表使用text方法,然后存储到两个空列表中。经过试验发现,爬取下来的地址存在大量的空格,因此,我们可以使用replace方法移除字符串中的空格,语法如:string.replace(A, B),意思是将string中的A转化为B,要注意的是,A和B的文本类型必须为字符串格式。
在7处,我们通过使用一个for遍历,将两个列表中对应的数据相结合,并在最后输出最终的查询结果。