专栏首页光城(guangcity)揭开神秘的面纱

揭开神秘的面纱

揭开神秘的面纱

0.说在前面

1.爬虫思想

2.selenium + chromdriver实现

3.获取参数,拼接请求

4.作者的话

0.说在前面

两种方式实现抓取ajax动态电话号码:

  • selenium + chromdriver实现
  • 获取参数,拼接请求

1.爬虫思想

打开f12检查页面后,刷新一下页面,点击Network,再点击下面的XHR,查看动态数据,会发现如下图所示,有两行数据。

加载前数据图

当我们点击查看电话时,会发现如下图所示,多了一行数据,那么接下来我们来点一下这个数据,查看详情!

加载后数据图

首先查看一下Headers里面的关键信息,如下面两图所示:

Headers数据图

请求参数图

在上图的Query String Parameters处点击同行的view URL encoded,会发现跟图1的Request URL一致。也就是说只我们按照图1的get方式请求对应的URL,应该即可获取到相应的数据,事实确实如此,就这么简单!

但是呢,每一个页面都有那些参数,难道我们每爬取一个页面就得重新改这些参数或者这么长的url?岂不是太复杂了,那么现在我们对其进行智能化处理。下图为我们获取的数据格式,只需要获得secret_phont对应的value即可!

响应结果图

那么我们来看一下未点击查看电话时候的源码,并从中获取以上的参数即可。在获取参数之前,自己去尝试几个不同的页面会发现,只有user_id、puid以及phone参数对应的值不一样,那么只需要获取这几个就可以了。

如下图为关键参数phone的页面(其余2个参数类似,就不展开说明了):

分析phone图

2.selenium实现

【类封装】

class selenium_spider(object):
    def __init__(self,url):
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
        }
        self.url = url
        http_list = get_IP()
        self.headers = headers
        self.http_list = http_list

【存储代理】

def save_proxies(self):
    ouf = open("valid_ip.txt", "a+")
    for each_proxies in self.http_list:
        ouf.write(str(each_proxies))
        ouf.write('\n')

【获取代理】

def avoid_verifi(self,url):
    # print(http_list)
    # print(len(http_list))
    while True:
        random_line = random.randint(1, len(self.http_list))
        theline = open('valid_ip.txt', 'r').readlines()[random_line]
        theline = theline.replace("'", '"')  # 单引号全部替换为双引号
        theline = json.loads(theline)  # str转dict(字典)格式
        print("正在使用的代理IP:" + str(theline))
        try:

            html = requests.get(url, headers=self.headers, proxies=theline).text
            # print(html)
            if "访问过于频繁,本次访问做以下验证码校验" not in html:
                for key, value in theline.items():
                    print(key) # key即为HTTP或HTTPS
                    print(value) 
                    return value # value即为HTTP://ip:port或者HTTPS://ip:port形式
        except Exception as e:
            print('.....')

【selenium实现】

def selnium_clawl(self,proxies):
    proxies = re.findall('(//.*)', proxies)[0]
    print(proxies)
    print(proxies.replace('//', '')) # http://ip:port提取处ip:port
    chromeOptions = webdriver.ChromeOptions()
    # 设置代理
    chromeOptions.add_argument('--proxy-server={0}'.format(proxies))
    driver = webdriver.Chrome(chrome_options=chromeOptions)
    driver.implicitly_wait(5)  # seconds
    driver.get(self.url)
    raw_phone = driver.find_element_by_xpath("//a[@class='phone_num js_person_phone']")
    raw_phone.click()
    time.sleep(5)  # 等待10s
    print(raw_phone.text)

注意:以上是添加代理后的代码,有可能因为代理问题无法正常爬取,只需要去掉代理便可以。

3.获取参数,拼接请求

【封装】

class phone_spider(object):
    def __init__(self,url):
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
        }
        http_list = get_IP()
        self.url = url
        self.headers = headers
        # [{},{}...]形式的代理
        self.http_list = http_list

【代理存储】

def save_proxies(self):
    ouf = open("valid_ip.txt", "a+")
    for each_proxies in self.http_list:
        ouf.write(str(each_proxies))
        ouf.write('\n')

【获取源码及代理】

def get_html(self):
    while True:
        random_line = random.randint(1, len(self.http_list))
        theline = open('valid_ip.txt', 'r').readlines()[random_line]
        theline = theline.replace("'", '"')  # 单引号全部替换为双引号
        theline = json.loads(theline)  # str转dict(字典)格式
        print("正在使用的代理IP:" + str(theline))
        try:
            headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
            }
            html = requests.get(self.url, headers=headers, proxies=theline).text
            # print(html)
            if "访问过于频繁,本次访问做以下验证码校验" not in html:
                return html,theline # 
        except Exception as e:
            print('.....')

【数据提取】

def get_Info(self):
    raw_html,proxies = self.get_html()
    selector = etree.HTML(raw_html)
    phone = selector.xpath('//div[@id="full_phone_show"]/@data-phone')[0]
    puid = selector.xpath('//input[@id="puid"]/@value')[0]
    user_id = selector.xpath('//input[@id="user_id_hide"]/@value')[0]
    name = selector.xpath('//div[@class="name"]/text()')[0]
    # 去掉name的回车换行及空格
    name = name.replace('\n','').replace(' ','')
    return phone,puid,user_id,name

【获取编码后的phone】

def encode_Phone(self):
    phone, puid, user_id, name = self.get_Info()
    # phone转为字典
    dict_phone = {}
    dict_phone["phone"] = phone
    # 传递字典phone
    encode_phone = parse.urlencode(dict_phone)
    return encode_phone

【获取请求的url前缀】

def url_Process(self):
    # 从http://cq.ganji.com/fang5/3552816612x.htm中提取处http://cq.ganji.com/
    url_head = re.findall(r'(.+.com/)', self.url)[0]
    return url_head

【参数拼接,发送请求】

def get_Phone(self):
    raw_html, proxies = self.get_html()
    phone, puid, user_id, name = self.get_Info()
    url_head = self.url_Process()
    encode_phone = self.encode_Phone()
    par_url = url_head + 'ajax.php?dir=house&module=secret_phone&user_id=' + user_id + '&puid=' + puid + '&major_index=5' + '&' + encode_phone + '&isPrivate=1'
    raw_data = requests.get(par_url, headers=self.headers, proxies=proxies).text
    return raw_data

【提取电话号码】

def phone_Extract(self):
    raw_data = self.get_Phone()
    data= json.loads(raw_data)
    return data["secret_phone"]

【类调用】

if __name__ == '__main__':
    url = 'http://cq.ganji.com/fang5/3552816612x.htm'
    ps = phone_spider(url)
    ps.save_proxies()
    raw_phone, puid, user_id, name= ps.get_Info()
    print("----------请求关键参数如下----------")
    table = pt(["raw_phone","puid","user_id"])
    table.add_row([raw_phone,puid,user_id])
    print(table)
    phone = ps.phone_Extract()
    print(name + '的联系电话为' + phone)

【结果呈现】

爬取结果图

4.作者的话

最后,如果您觉得本公众号对您有帮助,那么请您多多转发及支持! 阅读更多查看本节项目源码哦!

本文分享自微信公众号 - 光城(guangcity),作者:light-city

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-09-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如醉如痴之最小堆

    一道简单的题,可以让你如醉如痴,更是因为这一道题,你才会学会很多,不要小看简单,简单中蕴含深意。

    公众号guangcity
  • 1.8亿条海量Txt数据存储MySQL实践

    最近出去旅游了,嗨皮了嗨皮,明天上班,开始做作业,今日将1.8亿数据存储的方式进行总结,欢迎大家拍砖!

    公众号guangcity
  • 第二期编程实践之快乐数

    0.导语1.快乐数1.0 问题1.1 递归+哈希+循环1.2 非递归+哈希+循环1.3 循环替代1.4 哈希表替代1.5 数字4的作用2.作者的话

    公众号guangcity
  • Python接口自动化-8-测试报告

    HTMLTestRunner 是 Python 标准库的 unittest 模块的一个扩展。它生成易于使用的 HTML 测试报告 报告模板下载地址:http:/...

    企鹅号小编
  • Python类super()及私有属性原理解析

    砸漏
  • python编写的串口程序

    最近导师给了个GSM模块,需要通过RS232串口发送AT指令来对模块进行控制,于是看了看python的GUI设计和串口部分的资料,自己编写了一个串口发送的小程序...

    py3study
  • python入门-4:类与对象

    面对对象编程是最有效的软件编写方法之一,在面对对象编程中,编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。对象在python中可以说是无处不在,对象...

    王诗翔呀
  • python3多线程趣味详解

    python3的多线程很多人无法理解是怎么运行的,因此本文从程序猿的日常生活出发,写了一个由浅入深的多线程教程,这样子大家就不会觉得陌生了,多线程真的很简单很简...

    机器学习和大数据挖掘
  • python多线程学习笔记(超详细)

    python threading 多线程 一. Threading简介 首先看下面的没有用Threading的程序 import threading,time ...

    marsggbo
  • 【Rust投稿】从零实现消息中间件(3)-SUBLIST

    上一篇中提到subject是一种Trie树,在实现的过程中发现非常琐碎,也不好讲解,因此考虑先实现一个简单版本的.具体来说就是

    MikeLoveRust

扫码关注云+社区

领取腾讯云代金券