目标说明

利用scrapy抓取中新网新闻,关于自然灾害滑坡的全部国内新闻;要求主题为滑坡类新闻,包含灾害造成的经济损失等相关内容,并结合textrank算法,得到每篇新闻的关键词,便于后续文本挖掘分析。

网站分析

目标网站:http://sou.chinanews.com/advSearch.do

结合中新搜索平台的高级搜索的特点,搜索关键词设置为:滑坡 经济损失(以空格隔开),设置分类频道为国内,排序方式按照相关度。得到所有检索到的新闻如下:

共1000多条数据。

分析网站特点发现,给请求为异步加载,通过抓包工具Fiddler得到:

分析:

  POST提交,每次提交目标的url为:http://sou.chinanews.com/search.do

  提交参数如上所示,其中q表示关键词(抓包测试时只输入了一个关键词);

  ps表示每次显示的调试,adv=1表示高级搜索;day1,day2表示搜索时间,默认不写表示全部时间,channel=gn表示国内;

  继续点击下一页,通过对照得到一个新的参数:start,其中当start=0时,默认省略,表示第一页,每次下一页都增加10(设置的页面显示10)

  分析得到,每次点击下一页都是一个POST提交,参数相同,不同的是start

代码逻辑

使用命令:scrapy start project NewsChina创建项目,编写items.py文件,明确抓取字段(常用套路,第一步都是明确抓取字段)。这里只抓取标题和正文。常规操作:添加数据来源和抓取时间信息。

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html import scrapy class NewschinaItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field() # 数据来源
source = scrapy.Field()
# 抓取时间
utc_time = scrapy.Field()
# 新闻标题
title = scrapy.Field()
# 新闻内容
content = scrapy.Field()
# 关键词
keywords = scrapy.Field()

明确抓取字段后,使用命令:scrapy genspider newsChina 生成爬虫,开始编写爬虫逻辑,结合抓取网站的特点,做以下操作:

针对该网站的反爬措施,添加请求延迟、重试次数等待配置;

通过修改POST请求的time_scope字段,得到每一页数据,并解析数据中详情页的链接,然后对详情页链接请求,解析待抓取数据;

至于循环抓取和终止循环条件,结合实际网站各有不同,在代码中已有说明。

# -*- coding: utf-8 -*-
import re
import scrapy
from NewsChina.items import NewschinaItem class NewschinaSpider(scrapy.Spider):
name = 'newsChina'
# allowed_domains = ['sou.chinanews.com']
# start_urls = ['http://http://sou.chinanews.com/'] #爬虫设置
# handle_httpstatus_list = [403] # 403错误时抛出异常
custom_settings = {
"DOWNLOAD_DELAY": 2,
"RETRY_ENABLED": True,
} page = 0
# 提交参数
formdata = {
'field': 'content',
'q': '滑坡 经济损失',
'ps': '',
'start': '{}'.format(page * 10),
'adv': '',
'time_scope': '',
'day1': '',
'day2': '',
'channel': 'gn',
'creator': '',
'sort': '_score'
}
# 提交url
url = 'http://sou.chinanews.com/search.do' def start_requests(self): yield scrapy.FormRequest(
url=self.url,
formdata=self.formdata,
callback=self.parse
) def parse(self, response):
try:
last_page = response.xpath('//div[@id="pagediv"]/span/text()').extract()[-1]
# 匹配到尾页退出迭代
if last_page is '尾页':
return
except:
# 当匹配不到last_page时,说明已经爬取所有页面,xpath匹配失败
# 抛出异常,这就是我们的循环终止条件
# print("last_page:", response.url)
return link_list = response.xpath('//div[@id="news_list"]/table//tr/td/ul/li/a/@href').extract()
for link in link_list:
if link:
item = NewschinaItem()
# 访问详情页
yield scrapy.Request(link, callback=self.parse_detail, meta={'item': item}) # 循环调用,访问下一页
self.page += 1 # 下一页的开始,修改该参数得到新数据
self.formdata['start'] = '{}'.format(self.page * 10)
yield scrapy.FormRequest(
url=self.url,
formdata=self.formdata,
callback=self.parse
) # 从详情页中解析数据
def parse_detail(self, response):
"""
分析发现,中新网年份不同,所以网页的表现形式不同,
由于抓取的是所有的数据,因此同一个xpath可能只能匹配到部分的内容;
经过反复测试发现提取规则只有如下几条。提取标题有两套规则
提取正文有6套规则。
:param response:
:return:
"""
item = response.meta['item'] # 提取标题信息
if response.xpath('//h1/text()'):
item['title'] = response.xpath('//h1/text()').extract_first().strip()
elif response.xpath('//title/text()'):
item['title'] = response.xpath('//title/text()').extract_first().strip()
else:
print('title:', response.url) # 提取正文信息
try:
if response.xpath('//div[@id="ad0"]'):
item['content'] = response.xpath('//div[@id="ad0"]').xpath('string(.)').extract_first().strip()
elif response.xpath('//div[@class="left_zw"]'):
item['content'] = response.xpath('//div[@class="left_zw"]').xpath('string(.)').extract_first().strip()
elif response.xpath('//font[@id="Zoom"]'):
item['content'] = response.xpath('//font[@id="Zoom"]').xpath('string(.)').extract_first().strip()
elif response.xpath('//div[@id="qb"]'):
item['content'] = response.xpath('//div[@id="qb"]').xpath('string(.)').extract_first().strip()
elif response.xpath('//div[@class="video_con1_text_top"]/p'):
item['content'] = response.xpath('//div[@class="video_con1_text_top"]/p').xpath('string(.)').extract_first().strip()
else:
print('content:', response.url)
except:
# 测试发现中新网有一个网页的链接是空的,因此提前不到正文,做异常处理
print(response.url)
item['content'] = '' yield item

编写中间件,添加随机头信息:

# -*- coding: utf-8 -*-

# Define here the models for your spider middleware
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/spider-middleware.html
import random
from NewsChina.settings import USER_AGENTS as ua class NewsChinaSpiderMiddleware(object): def process_request(self, request, spider):
"""
给每一个请求随机分配一个代理
:param request:
:param spider:
:return:
"""
user_agent = random.choice(ua)
request.headers['User-Agent'] = user_agent

编写数据保存逻辑:

结合python的jieba模块的textrank算法,实现新闻的关键词抽取,并保存到excel或数据库中

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
from datetime import datetime
from jieba import analyse
from openpyxl import Workbook
import pymysql class KeyswordPipeline(object):
"""
添加数据来源及抓取时间;
结合textrank算法,抽取新闻中最重要的5个词,作为关键词
"""
def process_item(self, item, spider): # 数据来源
item['source'] = spider.name
# 抓取时间
item['utc_time'] = str(datetime.utcnow()) content = item['content']
keywords = ' '.join(analyse.textrank(content, topK=5)) # 关键词
item['keywords'] = keywords return item class NewsChinaExcelPipeline(object):
"""
数据保存
"""
def __init__(self):
self.wb = Workbook()
self.ws = self.wb.active
self.ws.append(['标题', '关键词', '正文', '数据来源', '抓取时间']) def process_item(self, item, spider): data = [item['title'], item['keywords'], item['content'], item['source'], item['utc_time']] self.ws.append(data)
self.wb.save('./news.xls') return item # class NewschinaPipeline(object):
# def __init__(self):
# self.conn = pymysql.connect(
# host='.......',
# port=3306,
# database='news_China',
# user='z',
# password='136833',
# charset='utf8'
# )
# # 实例一个游标
# self.cursor = self.conn.cursor()
#
# def process_item(self, item, spider):
# sql = """
# insert into ChinaNews(ID, 标题, 关键词, 正文, 数据来源, 抓取时间)
# values (%s, %s, %s, %s, %s, %s);"""
#
# values = [
# item['title'],
# item['keywords'],
# item['content'],
#
# item['source'],
# item['utc_time']
# ]
#
# self.cursor.execute(sql, values)
# self.conn.commit()
#
# return item
#
# def close_spider(self, spider):
# self.cursor.close()
# self.conn.close()

运行结果

完成代码

参见:https://github.com/zInPython/NewsChina

scrapy抓取中国新闻网新闻的更多相关文章

  1. scrapy抓取学院新闻报告

    抓取四川大学公共管理学院官网(http://ggglxy.scu.edu.cn)所有的新闻咨询. 实验流程 1.确定抓取目标.2.制定抓取规则.3.'编写/调试'抓取规则.4.获得抓取数据 1.确定抓 ...

  2. scrapy抓取豆瓣电影相关数据

    1. 任务分析及说明 目标网站:https://movie.douban.com/tag/#/ 抓取豆瓣电影上,中国大陆地区,相关电影数据约1000条:数据包括:电影名称.导演.主演.评分.电影类型. ...

  3. 通过Scrapy抓取QQ空间

    毕业设计题目就是用Scrapy抓取QQ空间的数据,最近毕业设计弄完了,来总结以下: 首先是模拟登录的问题: 由于Tencent对模拟登录比较讨厌,各个防备,而本人能力有限,所以做的最简单的,手动登录后 ...

  4. python scrapy 抓取脚本之家文章(scrapy 入门使用简介)

    老早之前就听说过python的scrapy.这是一个分布式爬虫的框架,可以让你轻松写出高性能的分布式异步爬虫.使用框架的最大好处当然就是不同重复造轮子了,因为有很多东西框架当中都有了,直接拿过来使用就 ...

  5. scrapy抓取淘宝女郎

    scrapy抓取淘宝女郎 准备工作 首先在淘宝女郎的首页这里查看,当然想要爬取更多的话,当然这里要查看翻页的url,不过这操蛋的地方就是这里的翻页是使用javascript加载的,这个就有点尴尬了,找 ...

  6. scrapy抓取拉勾网职位信息(一)——scrapy初识及lagou爬虫项目建立

    本次以scrapy抓取拉勾网职位信息作为scrapy学习的一个实战演练 python版本:3.7.1 框架:scrapy(pip直接安装可能会报错,如果是vc++环境不满足,建议直接安装一个visua ...

  7. scrapy抓取的中文结果乱码解决办法

    使用scrapy抓取的结果,中文默认是Unicode,无法显示中文. 中文默认是Unicode,如: \u5317\u4eac\u5927\u5b66 在setting文件中设置: FEED_EXPO ...

  8. 分布式爬虫:使用Scrapy抓取数据

    分布式爬虫:使用Scrapy抓取数据 Scrapy是Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据.Scrapy用途广泛,可以用于数据挖掘. ...

  9. 解决Scrapy抓取中文网页保存为json文件时中文不显示而是显示unicode的问题

    注意:此方法跟之前保存成json文件的写法有少许不同之处,注意区分 情境再现: 使用scrapy抓取中文网页,得到的数据类型是unicode,在控制台输出的话也是显示unicode,如下所示 {'au ...

随机推荐

  1. NetworkManager网络通讯_NetworkLobbyManager(三)

    此部分可以先建立游戏大厅,然后进入游戏,此处坑甚多耗费大量时间.国内百度出来的基本没靠谱的,一些专栏作家大V也不过是基本翻译了一下用户手册(坑啊),只能通过看youtube视频以及不停的翻阅用户手册解 ...

  2. 2018.8.8 python 初识函数

    主要内容: 1.函数定义 2.函数名,函数体以及函数的调用 3.函数的返回值 4.函数的参数 一.函数的定义 函数:对代码块和功能的封装和定义. 二.函数名.函数体及函数的调用 我们使用def关键字来 ...

  3. 小白学 Python(14):基础数据结构(集合)(上)

    人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...

  4. 学习笔记16_页面缓存/进程外Session

    *页面缓存:适用于访问量较高的网站 <%@OutputCache Duration="15"//缓存15秒  VaryByParam='*' //请求的任何一处发生改变,缓存 ...

  5. [2018-10-29] python开发个人资源共享网--第二天

    创建Django目录 startproject my_project 创建APP startapp my_app 手动创建的文件夹 log 日志 media 用户上传下载 static 静态文件 配置 ...

  6. vue学习之插槽

    插槽 插槽(Slot)是Vue提出来的一个概念,正如名字一样,插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性. 个人理解:我感觉插槽就是父组件控制插槽 ...

  7. 【ASP.NET Core学习】Entity Framework Core

    这里介绍在ASP.NET Core中使用EF Core,这里数据库选的是Sql Server 如何使用Sql Server 添加模型 && 数据库迁移 查询数据 保存数据 如何使用Sq ...

  8. SSM配置后可以访问静态html文件但无法访问其他后台接口的解决方案

    web.xml中的一段 <servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class> ...

  9. [AspNetCore 3.0 ] Blazor 服务端组件 Render, RenderFragment ,RenderTreeBuilder, CascadingValue/CascadingParameter 等等

    一.组件 支撑Blazor的是微软的两大成熟技术,Razor模板和SignalR,两者的交汇点就是组件.通常,我们从ComponentBase派生的类型,或者创建的.razor 文件,就可以称作组件. ...

  10. js取两位小数点

    var money = one.money; var tmoney = money.substr(0,money.indexOf(".")+3);