一个爬虫程序练习代码
上课讲了爬虫,这是课后练习敲的代码,上传以做存档,以及学习交流使用。
概要
一个爬虫程序练习代码,上课讲了爬虫,这是课后练习敲的代码,上传以作存档,以及学习交流使用。
整体流程
首先访问主网站界面,我们可以看到 商品房楼盘查询 的主界面,从主界面点击第一个选项我们可以进入 楼盘信息 界面,访问随意1个选项,我们会进入楼栋信息界面,该界面的html源码中包含一个“iframe”的标签,其中的src属性中的链接可以访问一个纯列表界面(只有绿色的列表没有别的信息)这个界面显然更方便之后的数据爬取。从楼盘信息 界面访问随便一个选项我们会进入房屋预(销)售信息界面 这里便是我们需要获取的信息。
明确了要获取的数据后,我们便要考虑如何存放数据,把每个界面3存放为一个单独列表显然数据量太大了,于是我们将获取到的信息存入一个csv文件中,表头为 “‘门牌’,‘套内面积’, ‘分摊面积’, ‘阳台面积’, ‘销售面积’, ‘建筑面积’, ‘房屋类型’”等信息,表名为楼栋地址在例子中为:“浑南区沈中大街17-2号”。
技术名词解释
1.Python:一种高级编程语言
2. BeautifulSoup:BeautifulSoup是一种Python库,用于从HTML和XML文件中提取数据。它提供了一种简单而直观的方法来遍历文档,搜索特定标记,并从这些标记中提取所需的数据。
3 fake_useragent: fake_useragent是一个Python第三方库,用于生成随机的用户代理字符串。
4 pathlib:pathlib 是 Python3.4 及以后版本中内置的一个模块,用于处理文件路径和目录路径。它提供了一种面向对象的、直观易用的路径操作方式,使得编写跨平台的可移植代码变得更加容易。
5 requests:requests是一个用于发送HTTP请求的Python第三方库。
6 csv、os:os库是Python标准库之一,提供了访问操作系统功能的接口。Python 的 CSV 模块是标准库中的一个模块,可以用于读取和写入 CSV 文件。
技术细节
href_get()函数:
首先第一步,我们看到可以从商品房楼盘查询 的表格访问的 楼盘信息表格,在这个HTML中访问下一页用的是http链接,同时我们还发现商品房楼盘查询的页面具有页码属性。于是我们定义了一个函数“href_get()”,该函数输入为page,即要获得的前几页数据。返回值为一个列表(href_list)该list中的每个链接(URL_LEVEL1)均可用于访问 楼盘信息界面。
#可控制的爬取第i个页面的hreflist,list中的每个链接可用于访问楼盘信息列表
import requests
from bs4 import BeautifulSoup
from urllib.request import urlopen
import urllib.request
def random_header():
from fake_useragent import UserAgent
# print("调用了随机head")
ua = UserAgent()
return {'User-Agent': ua.random}
def href_get(page):
from time import sleep
print("开始获取第"+str(page)+"页数据")
url = 'http://124.95.133.164/work/xjlp/new_building.jsp?'+"page="+str(page)
headers=random_header()
req = requests.get(url, headers=headers,timeout=5)
soup = BeautifulSoup(req.content, "html5lib", from_encoding="gbk")
tr_tags = soup.find_all('tr')
href_list = []
for tr_tag in tr_tags:
a_tags = tr_tag.find_all('a')
# print(a_tags)
for item in a_tags:
if (item.get('href', None).find('/work/xjlp/build_list.jsp?') >= 0):
href_get= 'http://124.95.133.164' + item.get('href', None)
# print(href_get)
href_list.append(href_get)
print("-",end="")
sleep(0.05)
print()
return href_list
a=1 #修改a的数据以获取前a页数据
for x in range(a):
headers = random_header()
y=x+1
# print(y)
a=href_get(int(y))
for i in range(len(a)):
print(a[i]) #打印href——list中的数据
print("====================")
print("第"+str(y)+"页数据获取完毕")
print("====================")
2.frame_list_get()函数:
我们观察 楼盘信息界面,我们发现有些房产当前可售套数为0,所以我们做下筛选,只访问可售套数不为0的楼栋地址并继续获取之后的内容。
我们定义的一个用于实现该步骤的函数:“frame_list_get(url)”,在这个函数中,我们的输入量为url,返回值是“iframe_list, namelist, len(namelist)”其中第一个list是主要内容,该list存放的是我们得到的每一个“可售套数不为0的”楼栋地址对应的src属性中的链接,后面两个返回值前者为链接对应的楼栋地址名字,后者为存放链接列表长度的值(此处由于代码设计,两个list的长度必然是一样的),这2者主要用于美化在测试代码的时候输出的值的可读性。
#encoding=utf8
##该部分代码实现了从楼盘信息列表到“楼盘分层分户链接列表”的获取
import requests
import numpy as np
from urllib.request import urlopen
import urllib.request
from bs4 import BeautifulSoup
from time import sleep
def random_header():
from fake_useragent import UserAgent
# print("调用了随机head")
ua = UserAgent()
return {'User-Agent': ua.random}
u = 'http://124.95.133.164/work/xjlp/build_list.jsp?xmmcid=2021_DC_00_1376&xmmc=居住商业(HN-20006号高深东路北-1地块)'
def frame_list_get(url):
head=random_header()
req = requests.get(url, headers=head,timeout=2)
soup = BeautifulSoup(req.content, "html5lib", from_encoding="gbk")
url_list = []
tag_list = []
iframe_list =[]
namelist=[]
for tr_tag in soup.find_all('tr'):
td_tag = tr_tag.find('td')
a_tag = tr_tag.find('td').find('a')
next_td_tag = td_tag.find_next_sibling('td')
if a_tag != None and next_td_tag !=None:
href = 'http://124.95.133.164' + a_tag.get('href')
buildingname=str(a_tag.string)
tag = int(next_td_tag.string)
if tag !=0: #筛选当前可售的
url_list.append(href)
tag_list.append(tag)
namelist.append(buildingname)
for url1 in url_list:
res2 = requests.get(url1, headers=head)
indexhtml2 = res2.content
soup2 = BeautifulSoup(indexhtml2, "html5lib", from_encoding="gbk")
iframe=soup2.find('iframe')
http_get=iframe.get('src')
iframe_list.append(http_get)
return(iframe_list,namelist,len(namelist))
def main():
a=frame_list_get(u)
for i in range(a[2]):
print(a[0][i]," ",a[1][i])#a[0][i]返回的是第i个url
if __name__ == '__main__':
main()
3.room_csv_get()函数:
现在我们访问一个函数2中输出的url 我们会来到***楼栋信息界面***这是每栋楼对应的每个房间的下一层链接的交互按钮,我们可以发现有几种不同的颜色对应不同的房间售出状态:
我们只需要获取可售的房间,现在我们访问一个状态为可售的房间,得到***房屋预(销)售信息***表格这其中的:
“‘门牌’,‘套内面积’, ‘分摊面积’, ‘阳台面积’, ‘销售面积’, ‘建筑面积’, ‘房屋类型’” 等属性便是我们要获取的数据,我们不难发现每个房间的下一层列表格式都和***房屋预(销)售信息***一样,那既然如此,我们该步的目的就是:“从URL_LEVEL2 访问分层分户列表并获取列表中可售的房间的信息,”为便于后期整理,我们将获取到的信息存入一个csv文件中,表头为 “‘门牌’,‘套内面积’, ‘分摊面积’, ‘阳台面积’, ‘销售面积’, ‘建筑面积’, ‘房屋类型’”等信息,表名为楼栋地址在例子中为:“浑南区沈中大街17-2号”。
于是我们定义一个函数:“room_csv_get(url,package_name)”在该函数中我们输入值为url,以及获取到的csv文件的存放文件夹名pack_name(在例子中为dataget)。我们只需输入URL_LEVEL2 便可直接获取到对应楼栋地址中所有可售房间的信息数据并写入一个名为楼栋地址名的csv文件中。
#从楼盘分层分户frame列表到csv
import requests,csv,os
from bs4 import BeautifulSoup
from urllib.request import urlopen
from bs4 import BeautifulSoup
from time import sleep
from pathlib import Path
a= 'http://124.95.133.164/work/xjlp/door_list2.jsp?houseid=7D1CEE26-BC34-4A34-9028-8CCD6CBD2DEE'
b= "dataget"
# c= {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.48'}
def random_header():
from fake_useragent import UserAgent
# print("调用了随机head")
ua = UserAgent()
return {'User-Agent': ua.random}
def room_csv_get(url,package_name):
head=random_header()
res = requests.get(url, headers=head)
indexhtml = res.content
soup = BeautifulSoup(indexhtml, "html5lib", from_encoding="gbk")
tr_tags = soup.find_all('tr')
onsell = []
for tr_tag in tr_tags: #从楼栋信息爬取目前可售状态的房间d
a_tags = tr_tag.find_all('a')
for item in a_tags:
if (item.get('href', None).find('可售') >= 0):
href_get= 'http://124.95.133.164' + item.get('href', None)
# print(href_get)
onsell.append(href_get)
final_data =[]
x=0
print("正在获取数据")
for url in onsell: #访问在售楼的下一层链接,即存储房子套内面积等信息的表格
res = requests.get(url, headers=head)
indexhtml = res.content
soup = BeautifulSoup(indexhtml, "html5lib", from_encoding="gbk")
tr_tags = soup.find_all('td', {'class': 'font_lan'})
row = []
for item in tr_tags:
row.append(item.text.strip())
print("-",end="")
final_data.append(row[2:9])
x += 1
if x %10 ==0:
sleep(5)#每爬10个让服务器歇会
text=row[1]#获取坐落
# print(x,end=",")
sleep(0.3)
csv_name=(text+".csv")
dir_path = Path(os.path.dirname(os.path.abspath(__file__))) / package_name
dir_path.mkdir(parents=True, exist_ok=True) # 如果文件夹已存在则不会报错
csv_file_path = dir_path / csv_name
print()
with open(csv_file_path, 'w',encoding='utf-8',newline='') as f:
writer = csv.writer(f)
writer.writerow(['门牌','套内面积', '分摊面积', '阳台面积', '销售面积', '建筑面积', '房屋类型'])
for row in final_data:
writer.writerow(row)
a = text+"数据获取完成"
print(a)
def main():
room_csv_get(a,b)
if __name__ == '__main__':
main()