用谷歌浏览器模拟打开天眼查网站并爬取需要的数据

转载请注明地址:http://www.cnblogs.com/bethansy/p/7683130.html

安装软件,部署各种环境

   (1)安装软件

       安装python3.6 和pycharm2017,都在官网上下载即可。注意安装python3.6时注意勾选添加环境变量,安装pycharm后,打开软件会让你激活,按照下面的步骤操作即可

第一步:一路默认到这个输入注册码的页面
第二步:选择中间的license输入http://idea.lanyus.com这个网址
第三步:浏览器打开http://idea.lanyus.com后,点击获得注册码,复制注册码
第四步:将复制的注册码粘贴到里activation对应的框里去
第五步:点击ok完成安装

(2)安装第三方库

    由于需要用浏览器模拟,需要用到selenium、pymysql等第三方库。我一般喜欢使用pip来进行安装,如何用pip进行第三方库的安装可以看我以前写的博客

http://www.cnblogs.com/bethansy/p/7029023.html

(3)由于需要python来操作chrome,所以还需要下载一个谷歌浏览器放在python本地目录下

第一步:首先保证本地电脑带有chrome

第二步:根据自己chrome版本下载相应的谷歌驱动,下载地址 http://blog.csdn.net/huilan_same/article/details/51896672

第三步:将下载好的驱动放在python安装目录下,如图所示

 

二、开始爬虫

 1.建立浏览器,打开指定路径的页面,输入用户名,密码,点击登陆

       driver = webdriver.Chrome()
        driver.get(url)

        # 模拟登陆
        driver.find_element_by_xpath(
            ".//*[@id='web-content']/div/div/div/div[2]/div/div[2]/div[2]/div[2]/div[2]/input"). \
            send_keys(username)
        driver.find_element_by_xpath(
            ".//*[@id='web-content']/div/div/div/div[2]/div/div[2]/div[2]/div[2]/div[3]/input"). \
            send_keys(password)
        driver.find_element_by_xpath(
            ".//*[@id='web-content']/div/div/div/div[2]/div/div[2]/div[2]/div[2]/div[5]").click()
        time.sleep(3)
        driver.refresh()

 注意其中的time.sleep(3)是让浏览器休眠3秒,模拟得像个人的操作,不然机器控制速度太快,会被目标网站识别出来

 2.输入搜索内容 ,点击查找按钮,跳转到第二张页面,选择相关度最高的第一条内容进行点击,跳转到第三张页面,此时网页上打开了两个窗口

 driver.find_element_by_xpath(".//*[@id='home-main-search']").send_keys(self.word)  # 输入搜索内容
 driver.find_element_by_xpath(".//*[@class='input-group-addon search_button']").click()  # 点击搜索

 3.转换句柄

    此时drive指针还在搜索框页面,但是我们要抓取的是弹开的第二张网页上的内容,于是需要driver的指针移动到第二张网页上。 

        now_handle = driver.current_window_handle
        all_handles = driver.window_handles
        for handle in all_handles:
            if handle != now_handle:
                # 输出待选择的窗口句柄
                print(handle)
                driver.switch_to.window(handle)

  4.抓取网页数据

(1)抓取网站基本信息

    页面展示如下,除了获取基本信息以外,还要获取每个表格的内容再对应放在不同的数据表中

 

<div class="company_header_width ie9Style"><div><span class="f18 in-block vertival-middle sec-c2" style="font-weight: 600">淘宝(中国)软件有限公司</span><span class="describeIcon point sec-c3 pl5" style="font-weight: 100;display: inline-block"><span class="tic tic-circle-question-o"></span><span class="discribeBox block"><span class="triangle-with-shadow"></span><span class="describeContent block f14" style="z-index: 100;line-height: 24px;"><span class="text-left sec-c2 block">企业名称:公司的名称和住所是公司登记的主要事项,也是设立公司的组织条件。<br>公司名称的意义主要有...<a class="float-right" href="/describe/name">详情&gt;</a></span><span class="position-abs text-center sec-c4 pl5 block" style="bottom: 5px;">* 以上数据由天眼查合作伙伴<span class="sec-cyel">北大法宝</span>提供</span></span></span></span><!--曾用名--><span class="pl10 sec-c3 f12">浏览<span class="pl4">43766</span></span><p class="f14 mt10" style="line-height: 1.42857143;"><span class="border-radio2 f12 pl8 pr8 pt3 pb3 company-tag mr5">高新企业</span><!--公司性质--><!--1,公司,2香港,3社会组织,4律所--><!--上市信息--></p><!--联系方式等--><div class="f14 sec-c2 mt10" style="line-height: 26px;"><div class="in-block vertical-top overflow-width mr20" style="width: 220px;"><span class="sec-c3">电话:</span><span>18768440137</span></div><div class="in-block vertical-top"><span class="in-block vertical-top sec-c3">邮箱:</span><span class="in-block vertical-top overflow-width emailWidth">暂无</span></div></div><div class="f14 sec-c2" style="line-height: 26px;"><div class="in-block vertical-top overflow-width mr20" style="width: 220px;"><span class="sec-c3">网址:</span><a target="_blank" href="http://www.atpanel.com" nofollow="" class="c9">http://www.atpanel.com</a></div><div class="in-block vertical-top"><span class="in-block vertical-top sec-c3">地址:</span><span class="in-block overflow-width vertical-top emailWidth" title="杭州市余杭区五常街道荆丰村">杭州市余杭区五常街道荆丰村</span></div></div></div><div class="sec-c2 over-hide" style="line-height: 24px;"><span><span class="sec-c3">简介:</span>淘宝(中国)软件有限公司成立于2004年12月07日,主要经营范围为研究、开发计算机软、硬...</span><script type="text/html" id="company_base_info_detail">
                  淘宝(中国)软件有限公司成立于2004年12月07日,主要经营范围为研究、开发计算机软、硬件,网络技术产品,多媒体产品等。
                </script><span class="c9 point hover_underline" onclick="companyDetail()">详情</span></div></div>

 

(1)获取公司的基本信息,例如名字,地址,邮编,简介等

 def baseInfo(self):
        base = self.driver.find_element_by_xpath("//div[@class='company_header_width ie9Style']/div")
        # base '淘宝(中国)软件有限公司浏览40770\n高新企业\n电话:18768440137邮箱:暂无\n网址:http://www.atpanel.com
        # 地址:杭州市余杭区五常街道荆丰村'
        name = base.text.split('浏览')[0]
        tel = base.text.split('电话:')[1].split('邮箱:')[0]
        liulan = base.text.split('浏览')[1].split('\n')[0]
        email = base.text.split('邮箱:')[1].split('\n')[0]
        web = base.text.split('网址:')[1].split('地址')[0]
        address = base.text.split('地址:')[1]
        abstract = self.driver.find_element_by_xpath("//div[@class='sec-c2 over-hide']//script")
        # 获取隐藏内容
        abstract = self.driver.execute_script("return arguments[0].textContent", abstract).strip()
        tabs = self.driver.find_elements_by_tag_name('table')
        rows = tabs[1].find_elements_by_tag_name('tr')
        cols = rows[0].find_elements_by_tag_name('td' and 'th')
        # 工商主策号
        reg_code = rows[0].find_elements_by_tag_name('td')[1].text
        # 注册地址
        reg_address = rows[5].find_elements_by_tag_name('td')[1].text
        # 英文名称
        english_name = rows[5].find_elements_by_tag_name('td')[1].text
        # 经营范围
        ent_range = rows[6].find_elements_by_tag_name('td')[1].text
        # 统一信用代码
        creditcode = rows[1].find_elements_by_tag_name('td')[1].text
        # 纳税人识别号
        tax_code = rows[2].find_elements_by_tag_name('td')[1].text
        # 营业期限
        deadline = rows[3].find_elements_by_tag_name('td')[1].text
        # 企业类型
        ent_type = rows[1].find_elements_by_tag_name('td')[3].text
        idd = str(uuid.uuid1())
        idd.replace('-', '')

        BasedInfo = (idd, name, tel, email, web, address, abstract, reg_code, reg_address, english_name, ent_range,
                     creditcode, tax_code, deadline, ent_type)

        self.base(BasedInfo)

    def base(self, baseing):
        conn = pymysql.connect(host='localhost', user='root', passwd='123', db='tianyan', port=3306, charset='utf8')
        cur = conn.cursor()  # 获取一个游标
        sql = "INSERT INTO ent_basic (ent_uid, ent_name, entPhone, entEmail, ent_url, ent_address, ent_desc," \
              " ent_reg_no,ent_reg_address, ent_english_name, ent_range, credit_code, tax_person_code, entDeadline, " \
              "ent_type) VALUES ( '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s' )"
        cur.execute(sql % baseing)
        conn.commit()
        cur.close()  # 关闭游标
        conn.close()  # 释放数据库资源

(2)获取网页表格信息

    查看源码发现所有的表格都一个共同的特征,所以通过查找所有id

tables = driver.find_elements_by_xpath("//div[contains(@id,'_container_')]")

 2.1 获取表格以后继续抓取需要的内容

 

   def jiexitable(self, x):
        rows = x.find_elements_by_tag_name('tr')
        # 第二个表格是th 有没有什么方法可以同时查找td或者th!!!!! and 和 or
        cols = rows[0].find_elements_by_tag_name('td' or 'th')
        result = [[0 for col in range(len(cols))] for row in range(len(rows))]
        # 创建一个二维列表
        for i in range(len(rows)):
            for j in range(len(cols)):
                result[i][j] = rows[i].find_elements_by_tag_name('td')[j].text
        return result

 2.2 判断是否有翻页标记

    表格下有翻页标记的,一般web元素中都有li标签,去获取li标签,如果有的话就进行翻页操作,继续获取第二页以及后面几页的内容

 

    def trytable(self, x):
        # 是否需要去掉get_attribute ,得到的是table的名字 ,若没得表格到flag则为0
        try:
            x.find_element_by_tag_name('table').get_attribute('class')
            flag = 1
        except Exception:
            flag = 0
            print("这不是表格")
        return flag

    def tryonclick(self, x):
        # 测试是否有翻页
        try:
            # 找到有翻页标记
            x.find_element_by_tag_name('ul')
            onclickflag = 1
        except Exception:
            print("没有翻页")
            onclickflag = 0
        return onclickflag

 2.3 点击翻页按钮 

 def jiexionclick(self, x, result):
        PageCount = x.find_element_by_xpath("//div[@class='total']").text
        PageCount = re.sub("\D", "", PageCount)  # 使用正则表达式取字符串中的数字 ;\D表示非数字的意思
        for i in range(PageCount - 1):
            button = x.find_element_by_xpath(".//li[@class='pagination-next  ']/a")
            button.click()
            table = x.find_element_by_tag_name('tbody')
            turnpagetable = self.jiexitable(table)
            result.append(turnpagetable)
        return result

    但是经常onclick按钮会出错,并提示这个元素没有click属性,所以以后抓取大型网站的数据最好还是用scrapy模块比较好。后来网友提醒用Firefox浏览器就不会存在这个问题了。

2.4 多条语句插入数据库

解析表格,将表格的内容一起插入数据库,在表格框架的基础上增加两列。分别是数据表的id和外键盘ent_uid ,在执行插入语句即可大功告成

    def jiexitable(self, x, id):
        rows = x.find_elements_by_tag_name('tr')
        # 第二个表格是th 有没有什么方法可以同时查找td或者th!!!!! and 和 or
        cols = rows[0].find_elements_by_tag_name('td' or 'th')
        result = [[0 for col in range(len(cols)+2)] for row in range(len(rows))]
        # 创建一个二维列表
        for i in range(len(rows)):
            result[i][0] = id
            idd = str(uuid.uuid1())
            idd = idd.replace('-', '')
            result[i][1] = idd
            for j in range(len(cols)):
                result[i][j+2] = rows[i].find_elements_by_tag_name('td')[j].text
        data = list(map(tuple, result)) # 将列表变成元组格式才能被插入数据库中
        return data
conn = pymysql.connect(host='10.2.1.190', user='root', passwd='123', db='tianyan', port=3306, charset='utf8')
    cur = conn.cursor()  # 获取一个游标
    sql = "INSERT INTO ent_competor ( idd,product, region, turn, industry, service, creat_time," \
          " estimate_value) VALUES ( '%s', '%s', '%s','%s','%s','%s','%s','%s' )"

    cur.executemany(sql, table)
    conn.commit()

 

5、完整代码

#!/usr/bin/python
# -*- coding: UTF-8 -*-
#  天眼查网站

import re
from selenium import webdriver
import time
import uuid
import conn_mysql

class mainAll(object):

    def __init__(self):
        self.url = 'https://www.tianyancha.com/login'
        self.username = '15160773967'
        self.password = 'yy171827'
        self.word = '淘宝'
        self.driver = self.login()
        self.scrapy(self.driver)
        print("ok,the work is done!")

    def login(self):
        driver = webdriver.Chrome()
        driver.get(self.url)

        # 模拟登陆
        driver.find_element_by_xpath(
            ".//*[@id='web-content']/div/div/div/div[2]/div/div[2]/div[2]/div[2]/div[2]/input"). \
            send_keys(self.username)
        driver.find_element_by_xpath(
            ".//*[@id='web-content']/div/div/div/div[2]/div/div[2]/div[2]/div[2]/div[3]/input"). \
            send_keys(self.password)
        driver.find_element_by_xpath(
            ".//*[@id='web-content']/div/div/div/div[2]/div/div[2]/div[2]/div[2]/div[5]").click()
        time.sleep(3)
        driver.refresh()
        # driver.get('https://www.tianyancha.com/company/28723141')

        # 模拟登陆完成,输入搜索内容
        driver.find_element_by_xpath(".//*[@id='home-main-search']").send_keys(self.word)  # 输入搜索内容
        driver.find_element_by_xpath(".//*[@class='input-group-addon search_button']").click()  # 点击搜索
        driver.implicitly_wait(10)

        # 选择相关度最高的搜索结果 第一条搜索框,然后再
        tag = driver.find_elements_by_xpath("//div[@class='search_right_item']")
        tag[0].find_element_by_tag_name('a').click()
        driver.implicitly_wait(5)

        # 转化句柄
        now_handle = driver.current_window_handle
        all_handles = driver.window_handles
        for handle in all_handles:
            if handle != now_handle:
                # 输出待选择的窗口句柄
                print(handle)
                driver.switch_to.window(handle)
        return driver

    #  获取所有表格和表单
    def scrapy(self, driver):
        tables = driver.find_elements_by_xpath("//div[contains(@id,'_container_')]")

        # 获取每个表格的名字
        c = '_container_'
        name = [0] * (len(tables) - 2)
        # 生成一个独一无二的十六位参数作为公司标记,一个公司对应一个,需要插入多个数据表
        id = 'word'
        table_list = [0] * (len(tables) - 2)
        for x in range(0, len(tables) - 2):
            name[x] = tables[x].get_attribute('id')
            name[x] = name[x].replace(c, '')  # 可以用这个名称去匹配数据库
            # 判断是表格还是表单
            num = tables[x].find_elements_by_tag_name('table')

            # 基本信息表table有两个
            if len(num) > 1:
                result = self.baseInfo(tables[x], id)
                self.inser_sql(name[x], result)

            #  单纯的表格
            elif len(num) == 1:
                table = tables[x].find_element_by_tag_name('tbody')
                table_list = self.jiexitable(table, id)
                onclickflag = self.tryonclick(tables[x])

                # 判断此表格是否有翻页功能
                if onclickflag == 1:
                    table_list = self.jiexionclick(tables[x], table_list)

                print(table_list)
            # 表单样式
            elif len(num) == 0:
                continue
            table_list + id
            self.inser_sql(name[x], table_list)

        print(name)
        return name

    def trytable(self, x):
        # 是否需要去掉get_attribute ,得到的是table的名字 ,若没得表格到flag则为0
        try:
            x.find_element_by_tag_name('table').get_attribute('class')
            flag = 1
        except Exception:
            flag = 0
            print("这不是表格")
        return flag

    def tryonclick(self, x):
        # 测试是否有翻页
        try:
            # 找到有翻页标记
            x.find_element_by_tag_name('ul')
            onclickflag = 1
        except Exception:
            print("没有翻页")
            onclickflag = 0
        return onclickflag

    def jiexionclick(self, x, result):
        PageCount = x.find_element_by_xpath("//div[@class='total']").text
        PageCount = re.sub("\D", "", PageCount)  # 使用正则表达式取字符串中的数字 ;\D表示非数字的意思
        for i in range(PageCount - 1):
            button = x.find_element_by_xpath(".//li[@class='pagination-next  ']/a")
            button.click()
            table = x.find_element_by_tag_name('tbody')
            turnpagetable = self.jiexitable(table)
            result.append(turnpagetable)
        return result

    def jiexitable(self, x, id):
        rows = x.find_elements_by_tag_name('tr')
        # 第二个表格是th 有没有什么方法可以同时查找td或者th!!!!! and 和 or
        cols = rows[0].find_elements_by_tag_name('td' or 'th')
        result = [[0 for col in range(len(cols)+2)] for row in range(len(rows))]
        # 创建一个二维列表
        for i in range(len(rows)):
            result[i][0] = id
            idd = str(uuid.uuid1())
            idd = idd.replace('-', '')
            result[i][1] = idd
            for j in range(len(cols)):
                result[i][j+2] = rows[i].find_elements_by_tag_name('td')[j].text
        data = list(map(tuple, result)) # 将列表变成元组格式才能被插入数据库中
        return data

    def baseInfo(self, idd):
        base = self.driver.find_element_by_xpath("//div[@class='company_header_width ie9Style']/div")
        # base '淘宝(中国)软件有限公司浏览40770\n高新企业\n电话:18768440137邮箱:暂无\n网址:http://www.atpanel.com
        # 地址:杭州市余杭区五常街道荆丰村'
        name = base.text.split('浏览')[0]
        tel = base.text.split('电话:')[1].split('邮箱:')[0]
        email = base.text.split('邮箱:')[1].split('\n')[0]
        web = base.text.split('网址:')[1].split('地址')[0]
        address = base.text.split('地址:')[1]
        abstract = self.driver.find_element_by_xpath("//div[@class='sec-c2 over-hide']//script")
        # 获取隐藏内容
        abstract = self.driver.execute_script("return arguments[0].textContent", abstract).strip()
        tabs = self.driver.find_elements_by_tag_name('table')
        rows = tabs[1].find_elements_by_tag_name('tr')
        cols = rows[0].find_elements_by_tag_name('td' and 'th')
        # 工商注册号
        reg_code = rows[0].find_elements_by_tag_name('td')[1].text
        # 注册地址
        reg_address = rows[5].find_elements_by_tag_name('td')[1].text
        # 英文名称
        english_name = rows[5].find_elements_by_tag_name('td')[1].text
        # 经营范围
        ent_range = rows[6].find_elements_by_tag_name('td')[1].text
        # 统一信用代码
        creditcode = rows[1].find_elements_by_tag_name('td')[1].text
        # 纳税人识别号
        tax_code = rows[2].find_elements_by_tag_name('td')[1].text
        # 营业期限
        deadline = rows[3].find_elements_by_tag_name('td')[1].text
        # 企业类型
        ent_type = rows[1].find_elements_by_tag_name('td')[3].text

        baseInfo = (idd, name, tel, email, web, address, abstract, reg_code, reg_address, english_name, ent_range,
                    creditcode, tax_code, deadline, ent_type)

        return baseInfo

    def inser_sql(self, title, table):

        if title == 'baseInfo':
            conn_mysql.baseInfo(table)
        elif title == 'staff':
            conn_mysql.staff(table)
        elif title == 'holder':
            conn_mysql.holder(table)
        elif title == 'invest':
            conn_mysql.invest(table)
        elif title == 'jingpin':
            conn_mysql.jingpin(table)

if __name__ == '__main__':
    mainAll()

 

这个脚本还有调用另一个叫conn_mysql.py的模块

    conn_mysql模块的内容如下所示:

import pymysql


def staff(table):
    # 名称 职位 公司名称  entuid
    conn = pymysql.connect(host='10.2.1.190', user='root', passwd='123', db='tianyan', port=3306, charset='utf8')
    cur = conn.cursor()  # 获取一个游标
    sql = "INSERT INTO person (ent_uid, name, role,entName,entUid) VALUES ( '%s', '%s')"
    cur.execute(sql % table)
    conn.commit()
    cur.close()  # 关闭游标
    conn.close()  # 释放数据库资源


def holder(table):
    # 并没有插入股东总量,出资从总额,认缴出资币种,直接从表格上爬取内容入库而已
    #  id ent_uid 股东名称 出资比例 认缴出资额
    conn = pymysql.connect(host='10.2.1.190', user='root', passwd='123', db='tianyan', port=3306, charset='utf8')
    cur = conn.cursor()  # 获取一个游标
    sql = "INSERT INTO share_holder (id, ent_uid, shaName, fundeRatio, subConam)" \
          " VALUES ( '%s', '%s', '%s','%s','%s')"
    cur.execute(sql % table)
    conn.commit()
    cur.close()  # 关闭游标
    conn.close()  # 释放数据库资源


def invest(table):
    #  id ,ent_uid, 投资设立企业名称,法人,建立日期(姑且当做注册日期),出资金额,企业状态
    conn = pymysql.connect(host='10.2.1.190', user='root', passwd='123', db='tianyan', port=3306, charset='utf8')
    cur = conn.cursor()  # 获取一个游标
    sql = "INSERT INTO outinvest (id, ent_uid, name, legalPerson, buildDate, regMoney,entStatus)" \
          " VALUES ( '%s', '%s', '%s','%s','%s','%s','%s' )"
    cur.execute(sql % table)
    conn.commit()
    cur.close()  # 关闭游标
    conn.close()


def base(table):

    conn = pymysql.connect(host='10.2.1.190', user='root', passwd='123', db='tianyan', port=3306, charset='utf8')
    cur = conn.cursor()  # 获取一个游标
    sql = "INSERT INTO ent_basic (ent_uid, ent_name, entPhone, entEmail, ent_url, ent_address, ent_desc," \
          " ent_reg_no,ent_reg_address, ent_english_name, ent_range, credit_code, tax_person_code, entDeadline, " \
          "ent_type) VALUES ( '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s' )"
    cur.execute(sql % table)
    conn.commit()
    cur.close()  # 关闭游标
    conn.close()  # 释放数据库资源


def jingpin(table):
    # 注意数据表设计的时候id是整数还是字符串,其他字段的字符串类型需要选择utf8
    conn = pymysql.connect(host='10.2.1.190', user='root', passwd='123', db='tianyan', port=3306, charset='utf8')
    cur = conn.cursor()  # 获取一个游标
    sql = "INSERT INTO ent_competor ( idd,product, region, turn, industry, service, creat_time," \
          " estimate_value) VALUES ( '%s', '%s', '%s','%s','%s','%s','%s','%s' )"

    cur.executemany(sql, table)
    conn.commit()
    cur.close()  # 关闭游标
    conn.close()  # 释放数据库资源

 

posted @ 2017-10-17 18:04  bethansy  阅读(13696)  评论(9编辑  收藏  举报