• 使用webdriver扒取网站小说(二)-----进阶篇(分层数据驱动)


    1.思路构想

    上一节主要通过webdriver写了一个demo来写了拔取小说的功能,虽然功能实现了,但是每次拔取不同的小说都要改很多数据,更改起来有很多不方便的地方,所以我们来吧数据层单独放在一起,并加入了日志等功能,下面首先来看一下我的文件分层结构吧!!!



    首先,我里面有文件夹和具体的实现文件,这只是我的初级构想,实际上还可以进行继续进一步的优化,比如把基础的功能单独放在一个文件夹里

    介绍一下我的结构吧

    data:放置excel表格,里面记录着驱动的数据,比如baseUrl、目录的xpath、日志路径、文件路径等等

    file:放置生成的txt小说

    log:放置日志文件,里面有拔取时的日志,方便后期进行查看

    excel:读取excel文件的代码

    readText:拔取小说的逻辑代码

    test:运行程序的代码


    2.代码实现


    首先我们的exccel读取时,引用了第三方的库:xlrd

    我们可以通过cmd进行安装:pip install xlrd

    读取excel文件的代码excel.py

    # coding=utf-8
    import xlwt
    import  xdrlib ,sys
    import xlrd
    
    def open_excel(file= 'file.xls'):
        try:
            data = xlrd.open_workbook(file)
            return data
        except Exception:
            print (Exception)
            
    
    def excel_table_byindex(file= 'file.xls',colnameindex=0,sheet_index=0):
        """根据索引获取Excel表格中的数据   参数:file:Excel文件路径     colnameindex:表头列名所在行的所以  ,sheet_index:表的索引"""
        data = open_excel(file)
        table = data.sheets()[sheet_index]
        nrows = table.nrows #行数
        ncols = table.ncols #列数
        colnames =  table.row_values(colnameindex) #某一行数据 
        list =[]
        for rownum in range(1,nrows):
    
             row = table.row_values(rownum)
             if row:
                 app = {}
                 for i in range(len(colnames)):
                    app[colnames[i]] = row[i] 
                 list.append(app)
        return list
    
    
    def excel_table_byname(file= '../test_data/abc.xlsx',colnameindex=0,sheet_name='Sheet1'):
        """根据名称获取Excel表格中的数据   参数:file:Excel文件路径     colnameindex:表头列名所在行的所以  ,sheet_index:Sheet1名称"""
        data = xlrd.open_workbook(file)
        table = data.sheet_by_name(sheet_name)
        nrows = table.nrows #行数 
        ncols =table.ncols      #列数    
        
        colnames =  table.row_values(colnameindex) #某一行数据 
        list =[]
        for rownum in range(1,nrows):
             row = table.row_values(rownum)
             if row:
                 app = {}
                 for i in range(ncols):
                    app[colnames[i]] = row[i]
                 list.append(app)
        return list
    
    
    def excel_get_valueFromTitle(list,colName,colValue):
        """  list : 列表         colName:列名      colValue列名值
              返回包含特定数据的一行(字典)
         """
        for row in list:
                if row[colName]== colValue:
                    return row
                   

    拔取小说内容的逻辑代码readText.py

    from selenium import webdriver
    import time
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By   
    import logging
    import sys
    
    class readTexts():
        
        def logger(self,logName):
            """ 获取logger"""
            self.logger =logging.getLogger()
            logger = self.logger
            formatter = logging.Formatter('%(asctime)s %(levelname)-8s: %(message)s')
            file_handler = logging.FileHandler(logName)
            file_handler.setFormatter(formatter)  
            console_handler = logging.StreamHandler(sys.stdout)
            console_handler.formatter = formatter 
            logger.addHandler(file_handler)
            logger.addHandler(console_handler)
            logger.setLevel(logging.INFO)
            return logger    
    
        def driver(self):
            """创建driver"""
            self.driver = webdriver.Chrome()
            return self.driver    
        
        def file(self,fileName):
            self.f = open(fileName,"w")
            return self.f
        
        def count(self,b):
            b= b+1
            return b
        def setA(self,a):
            self.a = a
            return a
        def setB(self,b):
            self.b = b
            return b
        def setC(self,c):
            self.c = c
            return c
        def setD(self,d):
            self.d = d
            return d
    #    def count(self,b):
    #        count=self.a+str(b)+self.c
    #        return count
        def doText(self,log,file,driver,baseUrl,locatePath,titlePath,textPath):
            logger = log
            driver = driver
            f= file
            driver.get(baseUrl)
            while self.b<self.d:
                try:
                    self.b= self.b+1
                    locateXpath =self.a+str(self.b)+self.c
                    print(locateXpath)
                   
                    WebDriverWait(driver,3,0.5).until(EC.presence_of_element_located((By.XPATH,locatePath)))
                    ele=driver.find_element_by_xpath(locateXpath)
                    newUrl =ele.get_attribute("href")
                    logger.info(newUrl )
                    driver.get(newUrl )
                    
                    title = WebDriverWait(driver,5,0.5).until(EC.presence_of_element_located((By.XPATH,titlePath)))
                    text = WebDriverWait(driver,3,0.5).until(EC.presence_of_element_located((By.XPATH,textPath)))
                    f.write(title.text)
                    f.write("
    ")
                    f.write(text.text)
                    f.write("
    ")
                    logger.info(title.text)
                    logger.info(self.b)
                    driver.back()
                except:
                    logger.error(Exception )
                    driver.get(baseUrl)
                
            driver.close()   
            f.close()
    
    
    
    控制运行层test.py

    import excel
    import readText as rt
    class tests():
        def mian(self):
            #通过excel获取数据
            excelList =excel.excel_table_byname("data/abc.xlsx", 0, "a")
            rows =excel.excel_get_valueFromTitle(excelList, "name", "黑铁之堡")
            #将数据通过字典传入到数据字段
            log = rt.readTexts.logger(self,rows["logname"])
            file = rt.readTexts.file(self,rows["filename"])
            driver = rt.readTexts.driver(self)
            rt.readTexts.setA(self,rows["a"])
            rt.readTexts.setB(self,rows["b"])
            rt.readTexts.setC(self,rows["c"])
            rt.readTexts.setD(self,rows["d"])
            baseUrl = rows["baseurl"]
            locatePath=rows["locatepath"]
            titlePath=rows["titlepath"]
            textPath=rows["textpath"]
            #记录日志
            log.info("loading字典数据:")
            log.info(rows)
            rt.readTexts.doText(self,log,file,driver,baseUrl,locatePath,titlePath,textPath)
    tests =tests()
    tests.mian()
    
    


    以及abc.xlsx中名字为a的sheet表

    filename logname a b c d baseurl locatepath titlepath textpath name
    file/校园狂神1.txt log/校园狂神1.log .//*[@id='chapterslist']/dl/dd[ 0 ]/a 1907 http://www.biquge5.com/10_10000/ .//*[@id='chapterslist']/dl/dt[2] .//*[@id='webbegin']/div[4]/div/div[2]/h1 .//*[@id='content'] 校园狂神
    file/黑铁之堡.txt log/黑铁之堡.log .//*[@id='list']/dl/dd[ 9 ]/a 2059 http://www.biquge.com/0_249 .//*[@id='footer']/div[2]/p[1] .//*[@id='wrapper']/div[5]/div[2]/div[2]/h1 .//*[@id='content'] 黑铁之堡





    最后我要说的是,我的代码还不是很完善,不过基本实现了数据驱动和日志记录的功能,需要改进的是循环的读取并保存小说和添加动态数据的逻辑代码,每次写完一些东西总是要总结的,这是推动每一次更改代码的动力。不过我在下面也试过加入新的功能,比如ddt数据驱动、unittest框架等等,不过因为一直没有调试好就不放上来了,下一次准备好好学习一下python的爬虫,毕竟webdriver的功能还是有些局限的,希望能用其他的库来实现更多有意思的事情。
  • 相关阅读:
    用GDB调试pgAdmin3
    C/C++中的函数重载(overloading)
    C语言中的数据对齐
    一个颓废男人的自我救赎
    python--文件操作
    总结还是记录都不重要,重要的是我裂了
    两数之和
    OSI参考模型体系结构
    不完美,才美
    AB逻辑
  • 原文地址:https://www.cnblogs.com/CCGGAAG/p/7800340.html
Copyright © 2020-2023  润新知