美文网首页
从零开始创建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