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("\n")
f.write(text.text)
f.write("\n")
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()
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的功能还是有些局限的,希望能用其他的库来实现更多有意思的事情。