• pyspider爬一批文章保存到word中


    最近一直在爬新闻,对于新闻爬取的套路还是比较熟悉的。一个群友发布了一个爬文章入word的任务,我果断接单,自我挑战一下,更何况完成任务还有赏金,哈哈。

    任务大概是这样的,有一个文章列表【http://www.shui5.cn/article/Bulletin/】,大约7W的量,每篇文章保存到一个word文件中。

    任务比较清晰,观察一下文章内容,发现所有的文章格式都是一致的,这样就比较简单了,只要能爬出一篇文章就搞定了。

    但是,现在有一个问题需要优先解决,就是如何用python操作word文档。

    第一步:何用python操作word文档

    首先明白一点,手动创建的以“.doc”或“.docx”结尾的文件并不是真正的word文件,以word文件的方式打开时会报错的。

    网上给的方法是使用python-docx扩展包。

    安装:

    pip install python-docx

    使用方法:

     1 #引入docx扩展包
     2 import docx
     3 
     4 #创建document 对象
     5 document = docx.Document()
     6 
     7 #添加标题,第二个参数是标题的等级
     8 document.add_heading(title, 1)
     9 
    10 #添加段落
    11 document.add_paragraph(content)
    12 
    13 #保存成一个docx文件
    14 document.save(file_name)

    我的需求是往word文档里添加标题和正文,没有图片,也不需要调整格式,所以有这几个接口就够用了。如果想查看更多接口,可以去这里https://python-docx.readthedocs.io/en/latest/index.html

    第二步:爬一篇文章试试

    首先分析一下页面结构,页面包含顶部导航、中间的文章列表和底部的分页。

    顶部导航是爬虫入口,从这12个分类开始,进入每个分类的文章列表

    中部是文章列表,底部是分页,先爬当前页的文章列表,然后从底部进入下一页的文章列表,直到没有下一页的时候。

    也可以爬完第一页的时候,分析后续页面的链接特征,同时爬剩下的所有页。但是这样会造成爬虫并发过大,导致一些不可预知的问题。

    我采用的是第一种,每次爬一页,然后从“下一页”的链接进入下一个文章列表,直到结束。

    先把最后的代码贴出来,再逐一说明

     1 #!/usr/bin/env python
     2 # -*- encoding: utf-8 -*-
     3 # Created on 2018-04-18 09:42:32
     4 # Project: 1
     5 
     6 from pyspider.libs.base_handler import *
     7 import re, docx
     8 
     9 URL_ARR = {
    10     'http://www.shui5.cn/article/FaGuiJieDu/'
    11 }
    12 
    13 class Handler(BaseHandler):
    14     crawl_config = {
    15     }
    16 
    17     @every(minutes=24 * 60)
    18     def on_start(self):
    19         
    20         #爬虫入口
    21         for each in URL_ARR:
    22             self.crawl(each, callback=self.news_list)
    23     
    24     #新闻列表
    25     @config(age=60 * 60) 
    26     def news_list(self, response):
    27         #当页新闻列表
    28         if response.doc('.arcList').html():
    29             for each in response.doc('.arcList a').items():
    30                 if re.match("http://www.shui5.cn/article/.", each.attr.href, re.U):
    31                     self.crawl(each.attr.href, callback=self.news_content)
    32         
    33         #下一页
    34         next_page_index = response.doc('.pagelist.clearfix a').length - 2
    35         if u"下一页" in response.doc('.pagelist.clearfix a').eq(next_page_index).text():
    36             url = response.doc('.pagelist.clearfix a').eq(total_pages).attr.href
    37             self.crawl(url, callback=self.news_list)
    38         
    39     #新闻内容
    40     @config(priority=2)
    41     @catch_status_code_error
    42     def news_content(self, response):
    43         
    44         if response.doc('.arcContent').html():
    45             document = docx.Document()
    46             title = response.doc('.articleTitle h1').text().replace('/', u'')
    47             document.add_heading(title, 1)
    48             for a in response.doc('.articleDes, .arcContent table p').items():
    49                 document.add_paragraph(a.text())
    50             file_name = (u'/pyspider/htmlfiles/wordFile/1/' + title + '.docx').encode('gbk')
    51             document.save(file_name)
    52         else:
    53            return {} 

    特别说明

     第46行代码

    title = response.doc('.articleTitle h1').text().replace('/', u'')

    这是取文章标题的逻辑,最后有个replace的操作,是因为有的文章标题中有“/”,document.save的时候,会把这个斜杠解析成一级目录,导致保存乱套,所以把标题中的斜杠都替换成顿号了。unicode编码表中没有中文顿号的符号,所以前面加u。

    还有50行代码

    file_name = (u'/pyspider/htmlfiles/wordFile/1/' + title + '.docx').encode('gbk')

    这句是拼word文件名称和保存路径的操作,最后有个encode操作,即编码成gbk,此处是有特殊含义的

    我们都知道,在python中默认的编码格式是unicode,而unicode能编码的字符比较少,遇到汉字就无能为力了,只能绕道走,通过把汉字编码成别的编码格式,然后储存第三方编码后的结果。具体的这种第三方编码选谁呢,我在代码第二行已经定义了,即utf-8。所以最后保存的word文件的名称和内容都是utf-8编码的。我的linux的默认编码格式是utf-8(你可以echo $LANG查看一下,或者通过修改/etc/profile文件来修改),所以在linux下是没啥问题的。关键是传输到windows下就出问题了。windows系统默认编码格式是gbk,而word内容的编码是utf-8,所以最后就看到word文件名称乱码而内容正常显示。这也就是我为什么在拼出word文档的标题后,要将它转码为gbk的原因了。

  • 相关阅读:
    Base64正反编码
    json数据测试接口
    ajax上传进度条
    ajax利用php上传图片
    ajax缓存 header头文件
    ajax同步与异步
    ajax的post请求与编码
    ajax的get请求与编码
    ajax获取服务器响应信息
    创建ajax对象
  • 原文地址:https://www.cnblogs.com/wangzhisdu/p/8872779.html
Copyright © 2020-2023  润新知