zoukankan      html  css  js  c++  java
  • Python爬取智联招聘职位信息

    这是一次失败的尝试 , 事情是这样的……

    1.起因
    前段时间刚刚学完爬虫,于是准备找个项目练练手。因为想要了解一下“数据挖掘”的职位招聘现状,所以我打算对‘智联招聘’下手了。网上当然也有很多教程,但是套路基本就是那几种情况,看起来也不是特别困难,我充满信心地开始了尝试。

    2.分析网站数据
    使用工具:谷歌浏览器、pycharm

    首先利用谷歌浏览器查看网页源码,发现在源码里找不到职位信息,所以判断职位信息是通过AJAX方式动态加载的。

    于是,我采用谷歌浏览器的开发者工具进行抓包分析数据。

    找到动态加载的文件后,分析该数据请求浏览器是怎么完成的。查看数据请求头信息,可以找到请求的URL。再看请求方式,是Post请求。于是分析post请求提交的参数。

    _v: 0.14465550
    x-zp-page-request-id: 6eed1fcaea9c498bab35d6943c3de160-1584539231050-802211
    x-zp-client-id: d09f083d-3339-4053-9687-34318fe5b0f6
    MmEwMD: 5HFRnmn4UlsY9o8zY2_zIQ0p5dKimKzxXlr6pjGK……

    很显然这是经过加密的几个参数,而且与时间戳有关。网上有关于解密的算法,但是如今的智联网站多了一层加密,就是‘MmEwMD:’参数。而且经过观察,这是几个参数是拼接在网址后面组合成数据请求的URL的,网上没有关于这方面的案例,因此强行爬取怕是不行,臣妾做不到啊!

    3.终极爬取方式 - 无头浏览器
    既然强攻不行,就不得不用爬虫的终极解决办法,就不信敲不开智联的“大门”。

    “工欲善其事,必先利其器。”

    因此,这里需要安装第三方库:selenium,并下载配置无头浏览器。有一个坑需要注意,就是pyhton已经不支持 phantomjs,所以我选择了Chromedriver(要与自己的谷歌浏览器版本相匹配)
    万事俱备只欠东风,一切准备妥当后,开始爬取尝试。

    数次尝试,发现总是报错,一番查看之后发现无头浏览器总是停留在初始页面,职位信息加载不出职位信息,我只好再次通过无头浏览器抓包查看问题出在哪一步。

    于是,我发现了动态加载请求文件的方式错了,本该是POST请求,现在提交的是OPTIONS请求,所以返回状态码400的错误。无头浏览器本应于普通浏览器一样,但是这里无头浏览器的请求方式却有变化。

    我猜想应该是智联网站采取了更严谨的反爬措施,能够识别无头浏览器。唉,费了老大劲,结果连职位信息的影子都没见着,技艺不精还需继续学习才好!


    4.初次爬取,终于失败

    从现在来看,要想爬取智联网站有两种方案可行:

    1.破解网站加密算法,并模拟加密算法

    2.修改无头浏览器请求数据方式,或者获得数据请求参数。

    可是,不管哪一种方法,都很难实现。虽然这次没有爬取成功,但这是一次‘顺藤摸瓜’的探索的过程,等到技术精湛的时候再来尝试!

    奉上这糟糕的代码:

    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC # 内置预期条件函数,具体API请参考此小节后API链接
    from selenium.webdriver.common.by import By # 内置定位器策略集
    #引入按键包
    # from selenium.webdriver.common.keys import Keys
    from lxml import etree
    import time
    import hashlib
    # import ssl
    # ssl._create_default_https_context = ssl._create_unverified_context
    from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
    # 过滤出数据请求中的headers
    def getHttpInfo(browser):
        for responseReceived in browser.get_log('performance'):
            try:
                response = json.loads(responseReceived[u'message'])[u'message'][u'params'][u'response']
                if 'ajaxUrl' in response['url']:
                    # print(response)
                    # print(response['url'])
                    # print(response['headers'])
                    # print(response['headersText'])
                    return response['requestHeaders']
            except:
                pass
        return None
    # 请求页面 并设置headers到文件中
    def setHeaders():
        d = DesiredCapabilities.CHROME
        d['loggingPrefs'] = { 'performance':'ALL' }
        options=webdriver.ChromeOptions()
        options.set_headless()
        options.add_argument('--disable-gpu')
        driver=webdriver.Chrome(desired_capabilities=d,options=options)
        driver.get('http://www.baidu.com')
        sleep(20)
        headers = getHttpInfo(driver)
        driver.quit()
        # write header
        hand = open('header.txt', 'w')
        hand.write(json.dumps(headers))
        hand.close()
    chrome_options = Options()
    #后面的两个是固定写法隐藏界面
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--disable-gpu')
    # 构建浏览器对象
    path = r'C:UsersAdministratorAppDataLocalGoogleChromeApplicationchromedriver.exe'
    browser = webdriver.Chrome(executable_path=path,chrome_options=chrome_options)
    # 获取网页文件,保存在文件中,page_source为JS动态加载后的页面
    url = 'https://sou.zhaopin.com/?jl=765&kw=%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98&kt=3'
    # 设置user-agent
    user_ag='Win7+ie9:Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; Tablet PC 2.0; .NET4.0E)'
    chrome_options.add_argument('user-agent=%s'%user_ag)
    # 隐式的等待
    # browser.implicitly_wait(3)
    browser.get(url)
    # 找到弹窗并点击消除
    elem = browser.find_element_by_xpath(r'//div[@class="risk-warning__content"]/button').click()
    print(getHttpInfo(browser))
    WebDriverWait(browser, 20, 0.5).until(EC.presence_of_all_elements_located((By.CLASS_NAME,'contentpile__content'))) #使用expected_conditions自带验证函数
    browser.save_screenshot('zhilain.png')
    js = 'document.documentElement.scrollTop=10000'
    browser.execute_script(js)
    time.sleep(3)
    # 保存网页截图
    html = browser.page_source
    print(html)
    browser.get_screenshot_as_file('test.png')
    browser.quit()
    ''' #####解密########(来源于网络)
    # 经过分析_v就是一个随机的8位小数
    # x-zp-page-request-id 由三部分组成,32位随机数据通过md5简单加密得到+ 当前时间戳 + 随机数6位
    # 想办法用python简单实现所谓的加密算法x-zp-page-request-id
    # 1、生成一个随机32位数id
    md5 = hashlib.md5()
    id = str(random.random())
    md5.update(id.encode('utf-8'))
    random_id = md5.hexdigest()
    #  2、生成当前时间戳
    now_time = int(time.time() * 1000)
    #  3、生成随机6位数
    randomnumb = int(random.random() * 1000000)
    # 组合代码生成x-zp-page-request-id
    x_zp_page_request_id = str(random_id) + '-' + str(now_time) + '-' + str(randomnumb)
    # print(x_zp_page_request_id)
    # 生成_v
    url_v = round(random.random(), 8)
    # print(url_v)
    '''
    
  • 相关阅读:
    Vuex2.0+Vue2.0构建备忘录应用实践
    一步步构造自己的vue2.0+webpack环境
    .NET入行之工作前
    webpack入门之简单例子跑起来
    vue中,class、内联style绑定、computed属性
    wap问答系统工作总结
    ASP.NET Core Api网关Ocelot的中文文档
    在pom.xml中添加Spring依赖
    【java基础】从反射开始(Reflection)
    【java基础】 == 和 equals() 的区别
  • 原文地址:https://www.cnblogs.com/slz99/p/12527717.html
Copyright © 2011-2022 走看看