【python网络爬虫与NLP系列】一、利用scrapy+redis实现新闻网站增量爬取_冰糖少女的博客-程序员ITS203_增量爬虫抓取实时新闻

技术标签: 爬虫  python  scrapy  redis  

写在前头:为了督促自己完成2018上半年的个人小任务,决定在平台上记录和分享完成的过程和心得。时间有限,但尽量详细具体吧。
简述一下整个系列的任务:(1)精选几个自己感兴趣的外文网站;(2)利用scrapy+redis框架实现几个网站的定时增量爬取;(3)定时基于自定义规则的新闻筛选;(4)文本预处理,并利用机器翻译模型对新闻进行翻译(5)定时对筛选后的新闻进行拼装整合(自然语言),加上固定格式和一些人性化的信息如当日当地天气、重大政策、重大预警等,并推动到微信或其他接口。
本文主要是完成整个任务中很基础且重要的一部分,即基于scrapy+redis框架的新闻数据爬取。本文以BusinessInsider网站为例,实现了基本的几个功能:获取新闻、解析内容、定时增量爬取

1. scrapy和redis安装

不管是Python2 还是python3,只要有pip,就能很轻松的安装Scrapy框架,直接在shell运行命令就自动化安装:

pip intsall Scrapy

redis安装稍微复杂些,可以参考redis安装 - 菜鸟教程 我是在mac下homebrew安装的,同样,首先在shell安装homebrew:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

安装完成后利用brew获取redis

brew install redis

安装后可以自测一下是否安装成功,能否使用如下命令启动redis-server

redis-server /usr/local/etc/redis.conf

之后,另启一个shell,输入redis-cli,进入redis客户端则安装成功,可通过简单的set, get进行测试。
这里写图片描述

同时,可以通过config set requirepass 「password」命令配置redis数据库的密码。到此处,scrapy和redis环境就安装成功了。最后,别忘了安装redis的python接口:

pip install redis

(如果没有数据自行下载安装mysql,mongodb等,本文例子中用文件形式替代数据库以便简化流程)

2. scrapy-redis项目

scrapy-redis项目是github上关注度较高的项目,它是非常优秀的解决多任务、分布式爬虫的框架,在多网站的增量爬取和部署方面非常优秀。需要注意的它的依赖:Python 2.7, 3.4 or 3.5 + Redis >= 2.8 + Scrapy >= 1.1 + redis-py >= 2.10。安装同样很简单。

pip install scrapy-redis

【写在coding之前】
为了更好地发挥scrapy_redis架构的优势,我们有必要先来熟悉一下整个项目的架构,详细介绍请自行完整阅读Scrapy-Redis架构分析
– Scrapy原生架构:
这里写图片描述

– Scrapy-redis架构
这里写图片描述
该架构即在原本Scrapy基础上引入了redis组件,即增加了快速的键值存储访问模式。更好地支持了多爬虫、分布式、网页增量与去重。

3. 创建scrapy-redis项目爬取新闻

具体流程与详解参考丁香园防封禁Scrapy-Redis实战
– 创建Spider

scrapy startproject newsCrawler

运行后你会发现生成了如下项目,此时还缺少一些必要的配置。
这里写图片描述

– 更新你的items
items.py就是你实际要爬取对象的实体类。在这里你可以定义你需要爬取的字段格式。当然你也可以继承NewscrawlerItem类并定义更多的实体类,比如增加图片、视频信息的item.这里我们以自动生成的NewcrawlerItem为例。

# -*- coding: utf-8 -*-
import scrapy

class NewscrawlerItem(scrapy.Item):
    # define the fields for your item here like:
    news_id = scrapy.Field()
    news_url = scrapy.Field()
    news_source = scrapy.Field()
    news_author = scrapy.Field()
    news_title = scrapy.Field()
    news_create_time = scrapy.Field()
    news_content = scrapy.Field()
    news_image_lst = scrapy.Field()
    pass

– 如果你需要爬取若干不同实体/网站,创建你需要的spider,命令如下:

scrapy genspider [options] <name> <domain>
# 以BusinessInsider为例
scrapy genspider -t basic BusinessInsider businessinsider.com

– 为了形成新闻爬取的框架,我有生成了一个NewsBasicSpider

scrapy genspider -t basic NewsBasic basic.com

然后在NewsBasic类中创建一些必要的新函数,如:

# -*- coding: utf-8 -*-
import scrapy
import logging
from newsCrawler.items import NewscrawlerItem
from newsCrawler.templates.BasicTmpl import BasicTmpl

class NewsBasicSpider(scrapy.Spider):

    tmpl = BasicTmpl
    def parse(self, response):
        links = response.xpath(BasicTmpl['link'])
        for link in links:
            link = self.parse_link(link, tmpl)
            yield scrapy.Request(url=link, callback=self.parse_item)

    def parse_item(self, response):
        news = NewscrawlerItem()
        try:
            news.news_url = response.url
            print news.news_url
            news.news_id = hash(news.news_url)
            news.news_source = self.name
            news.news_author = response.xpath(self.tmpl["author"]) or ""
            news.news_title = response.xpath(self.tmpl["title"]) or ""
            news.news_content = self.parse_content(response.xpath(self.tmpl["content"]) or "")
            news.news_image = self.parse_image(response.xpath(self.tmpl["image"]) or "")
            news.news_create_time = self.parse_time(response.xpath(self.tmpl["create_time"]) or "", tmpl)
            self.convert(news, self.tmpl)
            yield news
        except Exception as ex:
            logging.error("Parse Error: %s" % response.url)
            yield news

    def parse_image(self, image):
        return image

    def parse_link(self, link):
        return link

    def parse_time(self, create_time):
        return create_time

    def parse_content(self, content):
        return ""

    def convert(self, news):
        return news

需要注意的是,其中涉及到一个import进来的xpath模版BasicTmpl,是我根据新闻Item创建的一个dict。可以根据具体爬取的网站重新配置模版。模版在与spider平行的templates文件夹下创建。

BasicTmpl = {
    "link": "//a/@href",
    "author": '//meta[@property="author"]/@content/text()',
    "title": '//meta[@name="title"]/@content/text()',
    "create_time": '//meta[@name="date"]/@content/text()',
    "image": '//meta[@property="og:image"]/@content/text()',
    "content": '//article',
}

– 根据实际情况修改BusinessinsiderSpider.py
下面我们就来根据BusinessInsider网站的实际情况,继承NewsBasic类并实现必要的函数吧。例如我们在从网站通过xpath提取到content所在的container后,需要对container中的文字进行拆分和重组,并将文字中的配图以一定的格式替换掉。这个步骤可以通过overwrite NewsBasic中的parse_content()和parse_image()来实现~
我们此处创建一个最简的版本。
首先我们需要查看BusinessInsider网站创建相应的xpath模版。模版相当于只是对BasicTmpl个别字段进行了一定的更新。比如首页link的xpath。

from BasicTmpl import BasicTmpl
import copy
BusinessinsiderTmpl = copy.deepcopy(BasicTmpl)

update_xpath = {
    "link": '//a[@class="title"]/@href/text()',
}
BusinessinsiderTmpl.update(update_xpath)

接下来就可以来继承NewsBasicSpider创建BusinessinsiderSpider了~由于basic类中已经实现了一部分解析每个item的工作,我们这里只需要

# -*- coding: utf-8 -*-
import scrapy
from newsCrawler.items import NewscrawlerItem
from newsCrawler.templates.BusinessInsiderTmpl import BusinessinsiderTmpl
from newsCrawler.spiders.NewsBasic import NewsBasicSpider


class BusinessinsiderSpider(NewsBasicSpider):
    name = 'BusinessInsider'
    allowed_domains = ['businessinsider.com']
    start_urls = ['http://www.businessinsider.com/']
    tmpl = BusinessinsiderTmpl

    def parse(self, response):
        print self.tmpl['link']
        links = response.xpath(self.tmpl['link'])
        for link in links:
            yield scrapy.Request(url=link, callback=self.parse_item)   

至此,基本的代码工作可以先停一停,下周会来更新如何利用lxml和xpath完美爬取新闻正文并保存标记必要的图片。也就是检验新闻爬虫优劣的正文解析部分。

不过要想运行以上的代码,还需要在setting里进行些配置,来使爬虫的redis。需要的参数settings.py文件里有提示,我们先来介绍几个常用的参数配置。

DOWNLOAD_DELAY = 3
# The download delay setting will honor only one of:
CONCURRENT_REQUESTS_PER_DOMAIN = 4
CONCURRENT_REQUESTS_PER_IP = 10

# Enables scheduling storing requests queue in redis.
SCHEDULER = "scrapy_redis.scheduler.Scheduler"

# Ensure all spiders share same duplicates filter through redis.
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

# Configure item pipelines
# See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
    'scrapy_redis.pipelines.RedisPipeline': 300
}

# Specify the host and port to use when connecting to Redis (optional).
REDIS_HOST = '127.0.0.1'
REDIS_PORT = 6379
# Custom redis client parameters (i.e.: socket timeout, etc.)
REDIS_PARAMS  = {}
#REDIS_URL = 'redis://user:[email protected]:9001'
REDIS_PARAMS['password'] = '***'

看了前文提到的scrapy-redis架构文档的童鞋一定对ITEM_PIPELINES和Dupefilter有了比较深入的理解。Dupefilter依赖redis键值存储,对每个request查询是否已被处理过,实现新闻的增量去重爬取。pipeline即处理item的若干管道,管道与管道间存在先后关系。Redispipeline只是其中我们比较常见的item数据队列存储形式,当然你也可以实现你需要的pipeline对item进行更新和存储。

– 运行spider前还需要在shell中打开redis-server.

redis-server /usr/local/etc/redis.conf

– 测试BasicSpider

首先运行scrapy list查看现有的spiders,你会看到news和BusinessInsider

scrapy crawl BusinessInsider

不出意外的话,应该会看到log里显示

 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023
 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.businessinsider.com/robots.txt> (referer: None)
 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.businessinsider.com/> (referer: None)

不要慌,不要怕,这是因为网站针对咱们小蜘蛛们设置了防护门。下周有空我来讲讲如何通过random delay + user agent list + proxy list来解决反爬机制。

==还不知到穷学生党能不能买得起现在的代理==

先写到这些,最后整理一下必备的环境清单自己检查一下哦!

- redis数据库
- Anaconda2.x/3.x
  - requests
  - lxml
  - redis
  - Scrapy
  - scrapy-redis

当然这些平常用不到的话也可以conda create -n spider创建一个conda环境再来一个个安装,干净清爽些。把环境配好了剩下的下周继续~

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/TiffanyRabbit/article/details/80424355

智能推荐

IFeatureWorkspace.CreateFeatureClass on ArcServer_abjgt02882的博客-程序员ITS203

Subject IFeatureWorkspace.CreateFeatureClass on ArcServer Author Greg Walker ...

c语言 格式错误 acm,北大ACM第1006,我用C语言写的,调试时都是成功的为什么提交时出现Wrong Answer;请各位C语言大虾们看看..._Happy破鞋的博客-程序员ITS203

导航:网站首页 &gt;北大ACM第1006,我用C语言写的,调试时都是成功的为什么提交时出现Wrong Answer;请各位C语言大虾们看看时间:2019-7-14北大ACM第1006,我用C语言写的,调试时都是成功的为什么提交时出现Wrong Answer;请各位C语言大虾们看看Description人生来就有三个生理周期,分别为体力、感情和智力周期,它们的周期长度为23天、28天和33天.每...

mybatis一二级缓存_砂锅大的拳头的博客-程序员ITS203

### 1.缓存分类同hibernate一样,mybatis分为两级缓存:1.一级缓存:属于SqlSession范围内的缓存,属性内存级别的缓存(hibernate一级缓存,是Session范围内的缓存)2.二级缓存属于Mapper范围内的缓存,为同个mapper范围内的多个SqlSession共享的区域,但是Mybatis并没有对二级缓存提供实现,要依赖于第三方缓存厂商(EHCa...

STM32MP157嵌入式开发—1、Ubuntu环境搭建_PuddingHouChou的博客-程序员ITS203

第一部分:开发环境搭建要进行ARM嵌入式设备上的QT应用开发,首先需要搭建好的环境有:1、PC端Linux系统Ubuntu系统环境搭建2、Ubuntu下QT交叉编译环境搭建3、ARM板卡(STM32MP157)环境搭建 (ARM端带QT编译库的系统镜像烧录移植(采用正点原子编译好的出厂系统))4、编译含QT库的根文件系统(可自己拓展)二、Ubuntu系统环境搭建Linux 的开发需要在 Linux 系统下进行,这就要求我们的 PC 主机安装 Linux 系统,我们选择 Ubuntu 这个 Li

CV8-matching2_Remember00000的博客-程序员ITS203_census方法保留了窗口中像素的位置特征

特征描述将特征局部图像转化成描述特征的向量要求不变性;区分性;基于模板的匹配方法衡量算法SSD(Sum of Square Difference)SAD(Sum of Absolute Difference)NCC (Normalized Cross Correlation)利用子图与模板图的灰度,通过归一化的相关性度量公式来计算二者之间的匹配程度。没有归一化数值过大;Census Transform特征描述以一个像素为中心,对周围像素点进行编码,然后对两个匹配像素点进行异或

Wifi BT 地址格式_junwua的博客-程序员ITS203_bt地址

建议地址:X2:XX:XX :XX:XX:XXX3:XX:XX :XX:XX:XXX6:XX:XX :XX:XX:XXXA:XX:XX :XX:XX:XXXB:XX:XX :XX:XX:XXXB:XX:XX :XX:XX:XXStatic Device Address的特征可总结为:1)最高两个bit为“11”。2)剩余的46bits是一个随机数,不能全部为0,也不能全部为1。3)在一个上电周期内保持不变。4)下一次上电的时候可以改变。但不是强制...

随便推点

FPGA Verilog-1995 VS Verilog-2001_FPGA技术江湖的博客-程序员ITS203

今天给大侠带来FPGA Verilog 1995-VS Verilog-2001,话不多说,上货。2001年3月IEEE正式批准了Verilog‐2001标准(IEEE1364‐2001),与Verilog‐1995相比主要有以下提高。1、模块声明的扩展(1).Verilog‐2001允许将端口声明和数据类型声明放在同一条语句中,例子如下:(2).Verilog‐2001中增加了ANSIC风格的输入输出端口声明,可以用于module,task和function。例...

DML DDL DCL TCL_WS_HSY90的博客-程序员ITS203

接着上篇说起,数据库操作语句,看了网上说的,有很多种说法,我现在总结的为DML  DDL  DCL  TCL.DML (Data Manipulation Language)数据操纵语言statements are used for managing data within schema objects.由DBMS提供,用于让用户或程序员使用,实现对数据库中数据的操作。DML分成交互型DML和

android 文件地址格式,SharedPreferences的存储位置和格式_鱼板饭的博客-程序员ITS203

1.SharedPreferences 本身是一个接口,程序无法直接创建SharedPreferences实例,只能通过Context提供的getSharedPreferences(String name,int mode)来获取该实例该方法的第二个参数可以设置模式有:(1).Context.MODE_PRIVATE:指定该SharedPreferences数据只能被应用程序读写(2).Conte...

关于游戏汉化_技术宅也爱玩游戏的博客-程序员ITS203_游戏汉化怎么做

背景  很早很早以前就在研究游戏汉化了,只不过那个时候一直不想花太多精力在非工作的事情。最近(也不是最近了,应该是从2011年开始的),因为买了个PS3,又开始进行汉化工作了,而且也主要是从事PS3游戏的汉化。实际上PS3在国内不是很普及,不像PSP,PS3不及它的零头,导致了PS3几乎没有什么汉化组,也没有什么汉化作品。于是乎,我就专心研究PS3的汉化了。  也就是这段时间(近1个月),手里的事情稍微少一些了,才投入了较多精力到汉化上,目前为止,已经完成了5个游戏(实际上其中一个游戏是2011年完

菜鸟学习Android笔记-20140311_浅爱的博客-程序员ITS203

1、编写布局文件时,遇到这样的警告,“[I18N] Hardcoded string "昵称:", should use @string resource”    原来的代码: <TextView android:id="@+id/username" android:layout_width="fill_parent" android

用LR12录制app,用LR11跑场景,无并发数限制,已试验过,可行!_weixin_34075551的博客-程序员ITS203

免费使用LoadRunner对移动互联网后端服务器压力测试一、LoadRunner简介LoadRunner,是惠普公司研发的一款预测系统行为和性能的负载测试工具。通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题,LoadRunner能够对整个企业架构进行测试。LoadRunner11是目前比较常用的版本,有免费的超级license 最高支持6.5w个并发,目前该版本...

推荐文章

热门文章

相关标签