程序员

0125编程-58租房网爬虫-字体反爬破解

2019-01-25  本文已影响23人  zhyuzh3d

点击这里进入人工智能嘚吧嘚目录,观看全部文章


58同城租房网采用了字体反爬机制,利用字体对页面上的部分数字(如房价、面积平米数)进行了加密处理。

下面的代码包含了爬取房源基本信息并保存为文件的全部代码,在mac下运行有效,windows系统需要参照这里做些必要调整

以下是抓取房源列表页面并保存为多个html文件,注意更换你的headers内容。

header_str='''
accept: text/html
...
user-agent: Mozilla/5.0
'''
#字符串转dict
def str2dict(s,s1=';',s2='='):
    li=s.split(s1)
    res={}
    for kv in li:
        li2=kv.split(s2)
        if len(li2)>1:
            res[li2[0]]=li2[1]
    return res
headers=str2dict(header_str,'\n',': ')
#每页保存为本地html页面待用

import requests
import time

#地址为苏州市
urlstr = 'https://su.58.com/zufang/pn2/?PGTID=0d300008-0000-5965-8ce1-1873463f7758&ClickID={}'


def getPages(n, m):
    for i in range(n, m):
        print('GETING...', i)
        url = urlstr.format(i)
        res = requests.get(url, headers=headers)
        with open(r'./pages/{}.html'.format(i), 'w') as f:
            f.write(res.text)
        time.sleep(1)
    print('OK!')

getPages(9, 10)

以下是用于破解字体反爬加密的代码。
需要先安装模块,conda install -c mwcraig fonttools

from fontTools.ttLib import TTFont
import base64
import re
import io


def getKey(script):
    try:
        return re.findall(r"base64,(.*)'\).format", script)[0]
    except:
        return None


def getFont(key):
    data = base64.b64decode(key)
    fonts = TTFont(io.BytesIO(data))
    return fonts.getBestCmap()


def getDigit(str):
    d = re.findall(r'(\d+)', str)[0]
    return int(d) - 1


def getRealValue(script, string):
    key = getKey(script)
    fontMap = getFont(key)
    newMap = dict()
    #微软雅黑的对应的编码
    font58 = {
        '閏': '0x958f',
        '鸺': '0x9e3a',
        '麣': '0x9ea3',
        '餼': '0x993c',
        '鑶': '0x9476',
        '龤': '0x9fa4',
        '齤': '0x9f64',
        '龥': '0x9fa5',
        '龒': '0x9f92',
        '驋': '0x9a4b',
    }
    for key in fontMap.keys():
        value = getDigit(fontMap[key])
        key = hex(key)
        newMap[key] = value
    result = ''
    for char in string:
        temp = font58[char]
        value = newMap[temp]
        result = '%s%d' % (result, value)
    return int(result)

以下是从本地html文件读取数据并解密其中的数字。

from bs4 import BeautifulSoup
import os

files = os.listdir(r'./pages/')
file_li = [r'./pages/' + s for s in files]

items = []

for fp in file_li:
    with open(fp, 'r') as f:
        html = f.read()
        soup = BeautifulSoup(html)
        li = soup.find('ul', 'listUl').find_all('li')[:-1]
        script = soup.find('head').find_all('script')[-1:]

        for item in li:
            title = item.find('h2').text.strip()
            money = item.find('div', 'money').b.text.strip()
            money = getRealValue(script[0].text, money)
            roomtag = item.find('p', 'room strongbox')
            m2 = roomtag.text.split(' ')[-1:][0].replace('\xa0', '').replace(
                '㎡', '')
            m2li = m2.split('.')
            m2li2 = []
            for m in m2li:
                m2li2.append(str(getRealValue(script[0].text, m)))
            size = '.'.join(m2li2)

            items.append(dict(
                title=title,
                money=money,
                size=size,
            ))
print('OK!')

最后是将items对象写入json文件并测试读取。

import json
with open('items.json', 'w') as f:
    f.write(json.dumps(items))
print('Write OK!')
with open('items.json', 'r') as f:
    readItems=json.loads(f.read())
    print(readItems[10])
print('Read OK!')

点击这里进入人工智能DBD嘚吧嘚目录,观看全部文章


每个人的智能新时代

如果您发现文章错误,请不吝留言指正;
如果您觉得有用,请点喜欢;
如果您觉得很有用,欢迎转载~


END

上一篇下一篇

猜你喜欢

热点阅读