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

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

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

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

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

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

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

安装:

pip install python-docx

使用方法:

 #引入docx扩展包
import docx #创建document 对象
document = docx.Document() #添加标题,第二个参数是标题的等级
document.add_heading(title, 1) #添加段落
document.add_paragraph(content) #保存成一个docx文件
document.save(file_name)

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

第二步:爬一篇文章试试

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

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

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

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

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

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

 #!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2018-04-18 09:42:32
# Project: 1 from pyspider.libs.base_handler import *
import re, docx URL_ARR = {
'http://www.shui5.cn/article/FaGuiJieDu/'
} class Handler(BaseHandler):
crawl_config = {
} @every(minutes=24 * 60)
def on_start(self): #爬虫入口
for each in URL_ARR:
self.crawl(each, callback=self.news_list) #新闻列表
@config(age=60 * 60)
def news_list(self, response):
#当页新闻列表
if response.doc('.arcList').html():
for each in response.doc('.arcList a').items():
if re.match("http://www.shui5.cn/article/.", each.attr.href, re.U):
self.crawl(each.attr.href, callback=self.news_content) #下一页
next_page_index = response.doc('.pagelist.clearfix a').length - 2
if u"下一页" in response.doc('.pagelist.clearfix a').eq(next_page_index).text():
url = response.doc('.pagelist.clearfix a').eq(total_pages).attr.href
self.crawl(url, callback=self.news_list) #新闻内容
@config(priority=2)
@catch_status_code_error
def news_content(self, response): if response.doc('.arcContent').html():
document = docx.Document()
title = response.doc('.articleTitle h1').text().replace('/', u'、')
document.add_heading(title, 1)
for a in response.doc('.articleDes, .arcContent table p').items():
document.add_paragraph(a.text())
file_name = (u'/pyspider/htmlfiles/wordFile/1/' + title + '.docx').encode('gbk')
document.save(file_name)
else:
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的原因了。

pyspider爬一批文章保存到word中的更多相关文章

  1. python爬取数据保存到Excel中

    # -*- conding:utf-8 -*- # 1.两页的内容 # 2.抓取每页title和URL # 3.根据title创建文件,发送URL请求,提取数据 import requests fro ...

  2. 将爬取的数据保存到mysql中

    为了把数据保存到mysql费了很多周折,早上再来折腾,终于折腾好了 安装数据库 1.pip install pymysql(根据版本来装) 2.创建数据 打开终端 键入mysql -u root -p ...

  3. PHP操作:将数据库中的数据保存到Word、Excel中。

    1.首先要把word.excel表放到文件的根目录下 2.定义了一个word类 <?php class word { function start() { ob_start(); ob_star ...

  4. 1.scrapy爬取的数据保存到es中

    先建立es的mapping,也就是建立在es中建立一个空的Index,代码如下:执行后就会在es建lagou 这个index.     from datetime import datetime fr ...

  5. ffmpeg从AVFrame取出yuv数据到保存到char*中

    ffmpeg从AVFrame取出yuv数据到保存到char*中   很多人一直不知道怎么利用ffmpeg从AVFrame取出yuv数据到保存到char*中,下面代码将yuv420p和yuv422p的数 ...

  6. 将数字n转换为字符串并保存到s中

    将数字n转换为字符串并保存到s中 参考 C程序设计语言 #include <stdio.h> #include <string.h> //reverse函数: 倒置字符串s中各 ...

  7. Android把图片保存到SQLite中

    1.bitmap保存到SQLite 中 数据格式:Blob db.execSQL("Create table " + TABLE_NAME + "( _id INTEGE ...

  8. c# 抓取和解析网页,并将table数据保存到datatable中(其他格式也可以,自己去修改)

    使用HtmlAgilityPack 基础请参考这篇博客:https://www.cnblogs.com/fishyues/p/10232822.html 下面是根据抓取的页面string 来解析并保存 ...

  9. Flask实战第43天:把图片验证码和短信验证码保存到memcached中

    前面我们已经获取到图片验证码和短信验证码,但是我们还没有把它们保存起来.同样的,我们和之前的邮箱验证码一样,保存到memcached中 编辑commom.vews.py .. from utils i ...

随机推荐

  1. Hive数据倾斜

    数据倾斜是进行大数据计算时最经常遇到的问题之一.当我们在执行HiveQL或者运行MapReduce作业时候,如果遇到一直卡在map100%,reduce99%一般就是遇到了数据倾斜的问题.数据倾斜其实 ...

  2. [PHP] 算法-数组重复数字统计的PHP实现

    在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果输入长度为7的数组{ ...

  3. vsftpd-基于ftp协议的文件传输服务器软件

    第一部分:在Linux上部署vsftpd服务 1. vsftpd简介 1.1 vsftpd是什么? ftp(File Transfer Protocol)文件传输协议.(实现不同操作系统之间文件的传输 ...

  4. Raspberrypi 3B+ 安装 php+sqlite

    按照网上的命令都为安装php5-fpm 和 php5-sqlite, 但是发现无法找到软件,可能是系统版本比较高的缘故,原来的版本已经不支持了. 经过努力华找到如下安装方法 sudo apt-get ...

  5. opencv学习系列:连通域参考处理

    OpenCV里提取目标轮廓的函数是findContours,它的输入图像是一幅二值图像,输出的是每一个连通区域的轮廓点的集合:vector<vector<Point>>. 外层 ...

  6. python自动化开发-8

    进程与线程 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程. 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位. ...

  7. ssms2014和ssms2016版本错误定位的区别

    偶尔对比起2016以下的版本(比如ssms2014),ssms2016有一个小地方有区别.就是报错的行号有区别 举个例子,下面同样的语句在ssms2014和ssms2016里面运行.就是如下的效果 C ...

  8. 【HANA系列】SAP HANA XS使用Data Services查询CDS实体【一】

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA XS使用Dat ...

  9. [cb]SceneView 获取鼠标位置

    扩展需求 在Scene视图中获取鼠标的位置 Demo 在Scene视图中,当鼠标点击时实例化一个Cube 重点部分 实现代码 using UnityEngine; using UnityEditor; ...

  10. kettle 合并记录步骤中的 关键字段和 比较字段的说明

    该步骤用于将两个不同来源的数据合并,这两个来源的数据分别为旧数据和新数据,该步骤将旧数据和新数据按照指定的关键字匹配.比较.合并. 需要设置的参数: 旧数据来源:旧数据来源的步骤 新数据来源.新数据来 ...