疫情过去女朋友想去重庆玩,python批量爬取小猪短租重庆民宿信息
随着时间的流逝,在中国共产党的领导,全国人民的共同努力下,疫情逐渐受到了控制,逐渐好转,复工,开学有望。最近在和女朋友的闲聊当中得知她想五一去重庆你玩儿,上完网课后,闲来无事,就想的能不能直接把小猪短租上的重庆住宿信息批量爬取下来,顺便为自己的爬虫能力做做练习,话不多说,直接开整!
首先打开小猪短租的网页,给出第一页的 url:
url = 'https://cq.xiaozhu.com/search-duanzufang-p0-0/'
可以看出我选择的关键词是重庆,之后就会显示出民宿的信息,经过下拉浏览,我发现这个网页是使用页数来进行网页的跳转,我判断这个网页是静态网页。我先分析这个网页的请求,看看自己想要的内容在哪。
在Request Headers中是没有params参数列表这一项的,说明确实是通过点击不同的页数更改网页的url链接来更新网页的信息。再进行观察,并没有什么特别的地方,我感觉这和网页在构造请求头的时候只需要设置 User-Agent 即可,一会儿我就试试我的猜想。
在General中,可以看到Request URL 链接也没有跟的参数信息,使用的请求方法是GET,还可以看到服务器的IP地址等信息。
接着我点击不同的页数,复制每次的URL链接,看看它的变化规律:
https://cq.xiaozhu.com/search-duanzufang-p0-0/
https://cq.xiaozhu.com/search-duanzufang-p1-0/
https://cq.xiaozhu.com/search-duanzufang-p2-0/
可以发现它的变化仅仅在于p0,p1的变化,用来控页数,接着我们就来看看自己所要的信息在哪,由于判断是静态网页,在服务器返回的时候直接返回所有数据,那么源代码可能在第一个响应中:
果然我在第一个请求响应中找到网页未经渲染的源代码,并发现每一个房子的相关信息都存在 li 标签当中,然后我就开始着手写代码了,直接上代码:
导入的库(这里我才用Xpath的方法进行定点提取,所以导入了lxml库):
'''
小猪短租:重庆
'''
import time
import re
import requests
import lxml
from lxml import etree
获得网页源码:
def getHTMLText(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
}
try:
r = requests.get(url,headers = headers,timeout=5)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return '页面访问错误'
主方法构造网页链接列表:
if __name__ == '__main__':
# url = 'https://cq.xiaozhu.com/search-duanzufang-p0-0/'
url_list = []
#range 大小控制爬取房子信息的页数
for i in range(1):
i = str(i)
url = 'https://cq.xiaozhu.com/search-duanzufang-p' + i +'-0/'
url_list.append(url)
for i in url_list:
text = getHTMLText(i)
get_house_information(text)
使用Xpath提取房子信息,并进行输出(我将每个信息的源码标签写在每个Xpath的上方,这是我在编写代码的时候方便进行分析和编写代码):
def get_house_information(text):
tree = etree.HTML(text)
#<a target="_blank" href="https://cq.xiaozhu.com/fangzi/129561560803.html" class="resule_img_a">
house_href = tree.xpath('//a[contains(@target,"_blank") and @class="resule_img_a"]/@href')
# <img class="lodgeunitpic" title="磁器口古镇 川外西政 地铁站一室北欧大床整租"
house_name = tree.xpath('//img[@class="lodgeunitpic"]/@title')
# <span class="result_price">¥<i>238</i>起/晚</span>
house_price = tree.xpath('//span[@class="result_price"]//i/text()')
#<a class=="search_result_gridsum" href="https://www.xiaozhu.com/fangdong/105924673701/" target="_blank">
house_ownerInfo = tree.xpath('//a[contains(@class,"search_result_gridsum") and @target="_blank"]/@href')
# <em class="hiddenTxt">整套出租/1室0厅/1张床/宜住2人 <span class="commenthref">- 0条点评 </span></em>
house_size = tree.xpath('//em[@class="hiddenTxt"]/text()')
house_remark_num = tree.xpath('//em[@class="hiddenTxt"]/span[@class="commenthref"]/text()')
#返回值有换行符需要处理 normalize-space 我不建议这么做
house_size = sub_house_size(house_size)
house_remark_num = sub_house_remark_num(house_remark_num)
# <span class="col_slogn" title="速订:下单即可入住,无需房东确认"><i class="new_ico"></i>速订</span>
house_condition = tree.xpath('//span[@class="col_slogn"]/@title')
# print(house_size)
# print(house_remark_num)
for i in range(len(house_size)):
print('房子名称:{}'.format(house_name[i]))
print('房子一晚价格:{}'.format(house_price[i]))
print('房子大小:{}'.format(house_size[i]))
print('房子评论数:{}'.format(house_remark_num[i]))
print('房子入住信息:{}'.format(house_condition[i]))
print('房子详细链接:{}'.format(house_href[i]))
print('房子主人信息链接:{}'.format(house_ownerInfo[i]))
print('------------------------------------------------------------')
在这里我想强调的是Xpath对于爬取文本含空格符等信息的时候很难在爬取过程中直接进行处理,网上大多的方法是使用 normalize-space 方法,但这回只保留一个返回值,我不建议这么做,我建议另写函数用正则表达式对返沪文本中的空格符进行处理,所以对于房子的 house_size 和 house_remark_num 这两个信息在处理的时候,我另写了两个方法来对其进行处理:
def sub_house_size(list):
list_new = []
result = []
for i in list:
i = re.sub(r'\n','',i)
list_new.append(i)
for i in list_new[::2]:
result.append(i)
return result
def sub_house_remark_num(list):
result = []
for i in list:
i = re.sub(r'\n','',i)
result.append(i)
return result
这就是我全部的代码,后台执行结果:
自我感觉,对于这些静态网页的爬取,Xpath和CSS选择器代码量和方法更为简单和只管,现在自己已经开始不怎么喜欢使用BeautifulSoup方法了…
谢谢大家能看我写的分享😁