tesseract破解css反爬抓取自如租房信息

引言

作为一个刚毕业两年的打工人,在深圳这种房价压死人的城市,买房是不可能买房了,只能寄希望于租到一个便宜又舒适的房子。今天给大家带来的案例是tesseract破解css反爬抓取自如租房信息,将好房源尽收囊中。

一、分析页面

1、进入自如租房网站(url链接:https://sz.ziroom.com/z/p1/),打开页面,如图所示,城市选择深圳,可以看到,有很多租房信息,包括:房源名称、面积/层数、地理位置、价格,其中价格是比较重要的数据。
在这里插入图片描述
2、我们点击到第2页,可以看到网址变成了:https://sz.ziroom.com/z/p2/,如图所示。
在这里插入图片描述
3、因此只需要改变https://sz.ziroom.com/z/p{}/中的{}部分,就可以遍历爬取所有50页的内容。
4、我们按F12解析一下网页元素,可以看到,房源名称、面积/层数、地理位置等信息都位于标签div[@class=“info-box”]下相应位置,用xpath或者bs4可以快速定位获取,但价格信息却找不到。
在这里插入图片描述
5、由于价格属于较为重要的数据,此处做了css反爬,价格数据不是直接的数字,而是是通过数字图片和偏移像素定位的方式获得,再通过css渲染出来。因此要爬取该数据需先找到图片,然后用OCR文本识别方式识别文本,再通过相应的匹配方式还原出原始数据。废话不多说,开干!
在这里插入图片描述
在这里插入图片描述

二、代码实现

1、采用面向对象的方式实现,首先导入可能要用到的库,此处需要用到pytesseract和PIL库,需要先pip install安装。

import requests
import pytesseract
from PIL import Image
import time
from lxml import etree
import re
import csv

2、定义类并初始化类属性及实例属性,此处需要预先安装tesseract-ocr软件,并将其安装路径添加进来。

class ZiruSpider(object):
    pytesseract.pytesseract.tesseract_cmd = r'D:\Program Files\Tesseract-OCR\tesseract.exe'
    tessdata_dir_config = r'--tessdata-dir "D:\Program Files\Tesseract-OCR\tessdata"'
    csv_headers = ['name', 'area_floor', 'location', 'price']

    def __init__(self, page_num):
        self.urls = ['https://sz.ziroom.com/z/p{}/'.format(page) for page in range(1, page_num+1)]
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36"
        }
        self.offsets = ['-0px', '-21.4px', '-42.8px', '-64.2px', '-85.6px', '-107px', '-128.4px', '-149.8px', '-171.2px', '-192.6px']

3、定义获取响应内容的方法

    def get_response(self, url, headers):
        response = requests.get(url, headers=headers)
        response.encoding = 'utf-8'
        cont = response.text
        return cont

4、定义构造字典的方法,实现获取数字图片并识别出数字,并和像素偏移量一一对应形成字典。

    def make_dict(self, uprice):
        price_style = uprice.xpath('./span[@class="num"]/@style')[0]
        image_url = 'https:' + re.findall('background-image: url\((.*?)\);', price_style)[0]
        r = requests.get(image_url, headers=self.headers)
        with open('ziru.png', 'wb') as f:
            f.write(r.content)
        image = Image.open('ziru.png')
        text = pytesseract.image_to_string(image, lang='eng', config=self.tessdata_dir_config)
        nums = []
        for num in text:
            if num != ' ' and num != '\n':
                nums.append(num)
        dic = {}
        for k, v in zip(self.offsets, nums):
            dic[k] = v
        # print(dic)
        return dic

5、定义获得房租价格的方法。

    def get_price(self, uprice, num_dic):
        styles = uprice.xpath('./span[@class="num"]/@style')
        # print(styles)
        price = ''
        for style in styles:
            # print(style)
            px_num = style.split(';')[-1].split(':')[-1].strip()
            # print(px_num)
            num = num_dic[px_num]
            price += num
        # print(price)
        symble = uprice.xpath('./span[@class="rmb"]/text()')[0]
        unit = uprice.xpath('./span[@class="unit"]/text()')[0]
        price = symble + price + unit
        return price

6、定义处理网页并获取全部数据的方法。

    def parse_page(self, cont):
        html = etree.HTML(cont)
        data_list = []
        items = html.xpath('//div[@class="Z_list-box"]/div')
        for item in items:
            try:
                item_data = {}
                item_data['name'] = item.xpath('.//div[@class="info-box"]/h5/a/text()')[0]
                item_data['area_floor'] = item.xpath('.//div[@class="info-box"]/div[@class="desc"]/div[1]/text()')[0]
                item_data['location'] = item.xpath('.//div[@class="info-box"]/div[@class="desc"]/div[@class="location"]/text()')[0].strip()
                u_price = item.xpath('.//div[@class="info-box"]/div[@class="price "]')[0]
                img_dic = self.make_dict(u_price)
                item_data['price'] = self.get_price(u_price, img_dic)
                # print(uprice)
                print(item_data)
                data_list.append(item_data)
            except Exception as e:
                print('数据异常')
        return data_list

7、定义保存数据到csv的方法和实现主要逻辑的run方法,并定义main模块,这里我们演示爬取10页数据为例。

    def save_data(self, index, data):
        with open('ziru_info.csv', 'a', encoding='utf-8', newline='') as f:
            writer = csv.DictWriter(f, self.csv_headers)
            if index == 0:
                writer.writeheader()
            writer.writerows(data)

    def run(self):
        for index, url in enumerate(self.urls):
            cont = self.get_response(url, self.headers)
            page_data = self.parse_page(cont)
            # print(page_data)
            self.save_data(index, page_data)
            time.sleep(1)

            
if __name__ == '__main__':
    ziru_1 = ZiruSpider(10)
    ziru_1.run()

8、运行程序,如图所示,就得到想要的数据啦。
在这里插入图片描述
在这里插入图片描述
9、核对数据是否正确,如:我们挑选第3条数据,房源为“合租·港铁天颂5居室-南卧”的数据,可以发现,数据完全正确。大功告成!
在这里插入图片描述
在这里插入图片描述
小伙伴,你学会了吗?扫描下方二维码关注公众号,在后台回复“爬取自如租房”即可获取源代码。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值