美文网首页
从零开始创建Python项目

从零开始创建Python项目

作者: circle_hyy | 来源:发表于2020-02-11 15:14 被阅读0次

如果没有任何参考模板,需要快速从零创建一个爬虫项目,并且添加测试,需要怎么做呢。首先我们列一下整体计划,将要实现的功能分模块一步步实现。
目标:爬取菜鸟笔记前几页的笔记标题
使用语言和框架:Python+unittest+HTMLTestRunner
要实现的功能:

  • 爬取网页并获取数据
  • 保存爬取结果
  • 记录日志
  • 自动化测试
  • 保存测试报告

一、爬取网页并获取数据

1、请求
方法一和二使用urllib模块的请求方法,方法二添加了代理。方法三是用requests模块的请求方法。

# 方法一
def open_url(url):

    try:
        req = urllib.request.Request(url)
        req.add_header('user-agent',
                       'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/'
                       '68.0.3440.106 Safari/537.36')
        response = urllib.request.urlopen(req)
        html = response.read()
        return html
    except RequestException:
        return None
# 方法二
def agent_req(url):

    # 添加代理
    try:
        iplist = agent.get_agent()
        proxy_support = urllib.request.ProxyHandler({'http': random.choice(iplist)})
        opener = urllib.request.build_opener(proxy_support)
        opener.addheaders = [('user-agent',
                              'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/'
                              '68.0.3440.106 Safari/537.36')]
        urllib.request.install_opener(opener)
        response = urllib.request.urlopen(url)
        html = response.read()
        return html
    except RequestException:
        return None
# 方法三
def get_req(url):

    try:
        headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/'
                   '68.0.3440.106 Safari/537.36'
        }
        response = requests.get(url=url, headers=headers)
        response.encoding = "utf-8"
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        return None

2、获取页面HTML
在需要获取页面的地方调用想要的请求方法即可

def get_html(baseurl):

    html = request.get_req(baseurl)

    return html

3、获取目标数据
传入html页面、查找范围和偏移量,即可返回想要获取的数据

def get_data(html, a_field, b_field, num):

    datalist = []

    a = html.find(a_field)
    while a != -1:
        b = html.find(b_field, a, a + 255)
        if b != -1:
            if html[a + num:b] not in datalist:
                datalist.append(html[a + num:b])
        else:
            b = a + num
        a = html.find(a_field, b)

    return datalist

二、保存爬取结果

考虑到结果数据用excel打开方便,我们选择保存结果到csv文件

def save_data(datalist, file):

    # 保存文件
    a = 1
    os.chdir(config.get_path('project_path'))

    # 判断文件夹是否存在
    if os.path.exists('result'):
        pass
    else:
        os.mkdir('result')

    # 切换路径
    os.chdir(config.get_path('result_path'))
    filename = file + str(date.today()) +'.csv'

    with open(filename, 'a', newline='', encoding='utf-8') as wf:
        writer = csv.writer(wf, delimiter='-')
        # 先判断是否存在该文件
        with open(filename, 'r', encoding='utf-8') as rf:
            reader = csv.reader(rf)

            # 判断是否有表头
            if ['id-notename'] not in reader:
                writer.writerow(['id', 'notename'])
            # 判断已有行数
            for line in reader:
                a += 1

        for i in datalist:
            writer.writerow([a, i])
            a += 1
result.png
结果.png

运行完即可在result目录下保存当天数据

三、记录日志

class LogOutput:

    def log_output(self, name_project):

        now = time.strftime("%Y_%m_%d_%H_%M_%S")
        logging.basicConfig(level=logging.DEBUG,
                            filename=config.get_path('log_path') + '\\' + now + '- ' + name_project + '.log',
                            format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                            filemode='w',
                            datefmt='%Y-%m-%d %A %H:%M:%S')
        logger = logging.getLogger()
        logger.info(self)
log.png 日志文件.png

运行完即可在log目录下保存每次运行的日志

四、自动化测试

使用unittest框架,测试类需要继承unittest.TestCase

class NoteTest(unittest.TestCase):

    def setUp(self):

        saveLog.LogOutput().log_output('NoteTest')
        g = getArticle.GetNote()
        g.get_note()

    # 测试文件存在
    def test_fileExists(self):

        os.chdir(config.get_path('result_path'))
        self.assertTrue(os.path.exists('note' + str(date.today()) + '.csv'))
        logging.info('测试用例1:[note' + str(date.today()) + '.csv文件创建]运行通过')

    # 测试文件内容存在
    def test_resultSaved(self):

        with open('note' + str(date.today()) + '.csv', 'r', encoding='utf-8') as rf:
            reader = csv.reader(rf)
            self.assertIn(['id-notename'], reader)
            for i in reader:
                logging.info(i)
        logging.info('测试用例2:[文件中包含内容]运行通过')

    def tearDown(self):
        pass

五、保存测试报告

用HTMLTestRunner输出报告

if __name__ == '__main__':
    # unittest.main()
    suite = unittest.TestSuite()
    suite.addTest(NoteTest("test_fileExists"))
    suite.addTest(NoteTest("test_resultSaved"))
    html_file = config.get_path('report_path') + '\\report.html'
    with open(html_file, "wb") as fp:
        runner = HtmlTestRunner.HTMLTestRunner(stream=fp, title='mySpiderProject', description='测试用例')
        runner.run(suite)
测试结果.png

六、其它

这样,一个简易的项目创建成功了,可以将公共方法抽离出来优化代码,也可以继续补充如下额外功能。
1、为项目添加README文件
2、项目提交至GIT
3、Jenkins自动构建
4、邮件通知结果

相关文章

网友评论

      本文标题:从零开始创建Python项目

      本文链接:https://www.haomeiwen.com/subject/mbrxfhtx.html