python解析网页获取的数据如何去掉其中的空行ValueError: arrays must all be same length

今天做了一个python的一个比较小的实战案例:基于链家网二手房数据解析网页并从中获取如下信息:

  1. 标题
  2. 位置
  3. 房屋信息
  4. 关注人数 / 发布时间
  5. 房屋总价
  6. 房屋单价
  7. 备注信息

最后调用函数的时候报错ValueError: arrays must all be same length
如下面的两张图:
在这里插入图片描述
在这里插入图片描述
原来查看了一下他们的数据长度,发现有的数据长度为30,有的数据长度为60,如下图所示:
在这里插入图片描述
查看其中60的数据中,发现是空格和空行占据了1/2,如下图所示:
在这里插入图片描述
初步解决消除空格和空行的两种方法:

#写法一: 
#house_info_2 = [] 
#for i in house_info: 
#    house_info_2.append(re.sub('\s', '', i)) 
#写成如下形式:
house_info = html.xpath('//div[@class="info clear"]//div[@class="houseInfo"]/text()').extract() 
for i in house_info: 
    house_info.append(re.sub('\s', '', i))

#写法二:
#house_info_2 = [re.sub('\s', '', i) for i in house_info] 
#写成如下形式:
house_info1 = html.xpath('//div[@class="info clear"]//div[@class="houseInfo"]/text()').extract() 
house_info = [re.sub('\s', '', i) for i in house_info1] 
house_info

这种方法虽然把空格去掉了,但是有单引号单独占有的空行,长度仍为60,而其他数据的获取长度均为30
如下图所示:
在这里插入图片描述
再次进行修改:

#第一种——获取房屋信息
house_info = [re.sub('\s', '', i) for i in html.xpath('//li[@class="clear"]//div[@class="houseInfo"]/text()[2]').extract()]
print(len(house_info))

#第二种——获取房屋信息
house_info = [re.search(r'houseIcon"></span>(.*?)</div>', i, re.S).group(1)
              for i in html.xpath('//li[@class="clear"]//div[@class="houseInfo"]').extract()]
house_info_2 = [re.sub('\s', '', i) for i in house_info]
print(len(house_info_2))

结果如下:
在这里插入图片描述
在这里插入图片描述
这样就解决问题啦!!!
好啦,接下来记录一下我所写的所有的代码吧!!!

完整的代码如下:

#导入库
import pandas as pd 
import requests
import parsel
import re                    #使用正则表达式时要用到的库
import time
#获取URL
url = 'https://bd.ke.com/ershoufang/'

#添加headers
headers = {
    'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
}

#发起请求
r = requests.get(url, headers=headers)
print(r.text)

#解析网页
html = parsel.Selector(r.text)    #将其实例化成一个r.text,Selector对象为html
#获取标题
title = html.xpath('//div[@class="info clear"]/div[@class="title"]/a/text()').extract() 
print(len(title))

#获取位置
position = html.xpath('//div[@class="info clear"]//div[@class="positionInfo"]//a/text()').extract()
print(len(position))

#第一种——获取房屋信息
house_info = [re.sub('\s', '', i) for i in html.xpath('//li[@class="clear"]//div[@class="houseInfo"]/text()[2]').extract()]
print(len(house_info))

#第二种——获取房屋信息
house_info = [re.search(r'houseIcon"></span>(.*?)</div>', i, re.S).group(1)
              for i in html.xpath('//li[@class="clear"]//div[@class="houseInfo"]').extract()]
house_info_2 = [re.sub('\s', '', i) for i in house_info]
print(len(house_info_2))

# 关注信息
follow_info = [re.sub('\s', '', i) for i in html.xpath('//li[@class="clear"]//div[@class="followInfo"]/text()[2]').extract()]
print(len(title))

#获取房屋总价
#由于房价是由span标签和其下面的文本内容组成的,有两种方式
#第一种——将数字和单位万进行拼接
total_price = [i+'万' for i in html.xpath('//div[@class="info clear"]//div[@class="totalPrice"]/span/text()').extract()]
print(len(total_price))

#第二种——使用正则表达式
#'.'点表示匹配任意字符
#'*'星表示匹配零次或多次
#'?'问号表示非贪婪模式
total_price = [''.join(re.findall(r'<span>(.*?)</span>(.*?)</div>', i)[0]) 
               for i in html.xpath('//div[@class="info clear"]//div[@class="totalPrice"]').extract()] 
print(len(total_price))

#获取房屋单价
unit_price = html.xpath('//div[@class="info clear"]//div[@class="unitPrice"]/span/text()').extract()
print(len(unit_price))

# 获取备注信息
tag_info = [' | '.join(re.findall(r'[\u4e00-\u9fa5]+', i)) 
            for i in html.xpath('//div[@class="info clear"]//div[@class="tag"]').extract()]
print(len(tag_info))
# 将上述过程封装成函数
def get_lianjia_one_page(url):
    """功能:给定链家网二手房地址,获取一页的信息"""
    #添加headers
    headers = {
        'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
    }

    #发起请求
    r = requests.get(url, headers=headers)
    
    # 解析网页
    html = parsel.Selector(r.text)

    # 获取信息
    title = html.xpath('//div[@class="info clear"]/div[@class="title"]/a/text()').extract()
    position = html.xpath('//div[@class="info clear"]//div[@class="positionInfo"]//a/text()').extract()
    house_info = [re.sub('\s', '', i) for i in html.xpath('//li[@class="clear"]//div[@class="houseInfo"]/text()[2]').extract()]    
    follow_info = [re.sub('\s', '', i) for i in html.xpath('//li[@class="clear"]//div[@class="followInfo"]/text()[2]').extract()]
    total_price = [''.join(re.findall(r'<span>(.*?)</span>(.*?)</div>', i)[0]) 
                   for i in html.xpath('//div[@class="info clear"]//div[@class="totalPrice"]').extract()] 
    unit_price = html.xpath('//div[@class="info clear"]//div[@class="unitPrice"]/span/text()').extract()
    tag_info = [' | '.join(re.findall(r'[\u4e00-\u9fa5]+', i)) 
                for i in html.xpath('//div[@class="info clear"]//div[@class="tag"]').extract()]

    # 保存信息
    df_one = pd.DataFrame({
        'title': title,
        'position': position,
        'house_info': house_info,
        'follow_info': follow_info,
        'total_price': total_price,
        'unit_price': unit_price,
        'tag_info': tag_info
    })
    return df_one

# 获取URL
url = 'https://bd.ke.com/ershoufang/'

# 调用上面的函数
df_one = get_lianjia_one_page(url)
df_one.head() 

得到的结果如下:
在这里插入图片描述
但这样子的__得到的是一页的数据__,现在要得到多页数据

# 多页面
def get_lianjia_100_page(city_name):
    """
    功能:给定城市名,获取100页的信息
    """    
    df_all = pd.DataFrame()
    # 构建URL地址
    for page_num in range(100): 
        try:
            url = 'https://{}.ke.com/ershoufang/pg{}/'.format(city_name, page_num+1) 
            # 调用函数
            df_one = get_lianjia_one_page(url) 
            # 循环追加
            df_all = df_all.append(df_one, ignore_index=True)
            # 打印进度
            print('我正在获取第{}页的信息'.format(page_num+1), end='\r')
            # 休眠一秒
            time.sleep(1) 
        except Exception as e:
            break
    return df_all

#调用函数
df_all = get_lianjia_100_page(city_name='bd')  
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值