Scrapy框架:爬取网易新闻四大板块数据

简介:本文主要记录了学习Scrapy框架的成果,以及Selenium模拟浏览器和SQLite数据库的简单应用。


前言

需求:利用Scrapy框架爬取<网易新闻>四大常用板块(国内、国际、军事、无人机)首页的数据,包括标题、来源以及内容,并存储到数据库中。


提示:以下是本篇文章正文内容,下面案例可供参考

一、Scrapy是什么?

1.Scrapy简介

(1)Scrapy是适用于Python的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。
(2)Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。
(3)Scrapy最吸引人的地方就在于它是一个框架,任何人都可以根据需求方便快捷的修改。

2.Scrapy架构

Scrapy Engine(引擎):负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。
Scheduler(调度器):它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。
Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理。
Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器)。
Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方。
Downloader Middlewares(下载中间件):一个可以自定义扩展下载功能的组件。
Spider Middlewares(Spider中间件):一个可以自定扩展和操作引擎和Spider中间通信的功能组件。

在这里插入图片描述

二、拓展知识(Selenium、SQLite)

1.什么是Selenium?

(1)Selenium 是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样,其中支持的浏览器包括IE,Firefox,Safari,Chrome等。Selenium 是一套完整的web应用程序测试系统,包含了测试的录制Selenium IDE),编写及运行(Selenium Remote Control)和测试的并行处理(Selenium Grid)。
(2)Selenium的核心Selenium Core基于JsUnit,完全由JavaScript编写,因此可以用于任何支持JavaScript的浏览器上。
(3)Selenium可以模拟真实浏览器,自动化测试工具,支持多种浏览器,爬虫中主要用来解决JavaScript渲染问题。

Selenium的基本用法

from selenium import webdriver # 导入库

bro = webdriver.Chrome(executable_path='chromedriver.exe') # 声明浏览器
url = 'https:www.baidu.com'
bro.get(url) # 打开浏览器预设网址
print(bro.page_source) # 打印网页源代码

bro.quit() # 关闭浏览器

上述代码运行后,会自动打开Chrome浏览器,并登陆百度打印百度首页的源代码,然后关闭浏览器。

2.什么是SQLite?

(1)SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库不一样,您不需要在系统中配置。
(2)就像其他数据库,SQLite 引擎不是一个独立的进程,可以按应用程序需求进行静态或动态连接。SQLite 直接访问其存储文件。

SQLite的基本用法

import sqlite3

conn = sqlite3.connect('wudilibai.db')
cur = conn.cursor()
sql = 'insert into libai (title, content) values (?, ?)'
data = ('千年之狐', '十步杀一人,千里不留行。')
cur.execute(sql, data)
conn.commit()

cur.close()
conn.close()

上述代码运行后,会自动将data里的数据传入到名叫wudilibai的数据库里。

三、具体步骤

1.spider.py文件

代码如下:

import scrapy
from selenium import webdriver
from wangyixinwen.items import WangyixinwenItem

class WangyiSpider(scrapy.Spider):
    name = 'wangyi'
    # allowed_domains = ['wangyi.com']
    start_urls = ['https://news.163.com/']
    model_urls = []  # 存储四个板块对应详情页的url

    # 实例化一个浏览器对象
    def __init__(self):
        super().__init__()
        self.bro = webdriver.Chrome(executable_path='chromedriver.exe') # 只打开一次模拟浏览器

    def parse(self, response):
        li_list = response.xpath('//*[@id="index2016_wrap"]/div[1]/div[2]/div[2]/div[2]/div[2]/div/ul/li')
        model_list = [3, 4, 6, 8]
        for index in model_list:
            model_url = li_list[index].xpath('./a/@href').extract_first()
            self.model_urls.append(model_url)

        # 依次对每一个板块对应的页面进行请求
        for url in self.model_urls:  # 对每一个板块的url进行请求发送
            yield scrapy.Request(url=url, callback=self.parse_model)

    # 每一个板块对应的新闻标题相关的内容都是动态加载
    def parse_model(self, response):  # 解析每一个板块页面中对应新闻的标题和新闻详情页的url
        div_list = response.xpath('/html/body/div[1]/div[3]/div[4]/div[1]/div/div/ul/li/div/div')
        for div in div_list:
            title = div.xpath('./div/div[1]/h3/a/text()').extract_first()
            new_detail_url = div.xpath('./div/div[1]/h3/a/@href').extract_first()

            item = WangyixinwenItem()  # 实例化一个item对象
            item['title'] = title  # 把抓取到的title放入到item对象中

            # 对新闻详情页的url发起请求,meta是一个字典,用来把item对象传出去
            yield scrapy.Request(url=new_detail_url, callback=self.parse_detail, meta={'item': item})

    def parse_detail(self, response):  # 解析新闻内容
        sourse = response.xpath('//*[@id="ne_article_source"]/text()').extract_first()
        content = response.xpath('//*[@id="endText"]/p/text()').extract()

        # ''.join()把列表中的元素连接成一个字符串,strip()去掉换行,replace(" ", "")去掉看空格
        content = ''.join(content).strip().replace(" ", "")

        item = response.meta['item']
        item['sourse'] = sourse
        item['content'] = content

        yield item # 将item对象提交给piplelines(管道文件),用于持久化存储

    def closed(self, spider):
        self.bro.quit()  # 关闭模拟浏览器
        

2.items.py文件

代码如下:

import scrapy

class WangyixinwenItem(scrapy.Item):
    title = scrapy.Field()
    sourse = scrapy.Field()
    content = scrapy.Field()
    

3.middlewares.py文件

代码如下:

from scrapy.http import HtmlResponse
from time import sleep
class WangyixinwenDownloaderMiddleware:

    def process_request(self, request, spider):
        # Called for each request that goes through the downloader
        # middleware.

        # Must either:
        # - return None: continue processing this request
        # - or return a Response object
        # - or return a Request object
        # - or raise IgnoreRequest: process_exception() methods of
        #   installed downloader middleware will be called
        return None

    def process_response(self, request, response, spider): # spider爬虫对象
        bro = spider.bro # 获取了在爬虫类中定义的浏览器对象

        # 挑选出指定的响应对象进行篡改
        # 通过url指定request
        # 通过request指定response
        if request.url in spider.model_urls:
            bro.get(request.url) # 五个板块对应的url进行请求
            sleep(3)  # 睡眠3秒,预防反爬虫
            page_text = bro.page_source  # 包含了动态加载的新闻数据

            # response是四大板块对应的响应对象
            # 针对定位到的这些response进行篡改
            # 实例化一个新的响应对象(符合需求:包含动态加载出的新闻数据),替代原来旧的响应对象
            # 如何获取动态加载出的新闻数据?(基于selenium便捷的获取动态加载数据)
            new_response = HtmlResponse(url=request.url,body=page_text,encoding='utf-8',request=request)
            return new_response
        else:
            #response是其他请求对应的响应对象
            return response

    def process_exception(self, request, exception, spider):
        # Called when a download handler or a process_request()
        # (from other downloader middleware) raises an exception.

        # Must either:
        # - return None: continue processing this exception
        # - return a Response object: stops process_exception() chain
        # - return a Request object: stops process_exception() chain
        pass

4.pipelines.py文件

代码如下:

import sqlite3

class Sqlite3Pipeline(object):

    def open_spider(self, spider):
        print('开始导入数据库。。。')
        self.conn = sqlite3.connect('E:\学习研究\python爬虫\爬虫课件\南茹旅舍\wangyixinwen\wangyi_news.db')
        self.cur = self.conn.cursor()

    def process_item(self, item, spider):
        insert_sql = "insert into wangyi(标题, 来源, 内容) " \
                     "values (?, ?, ?)"

        data = (item['title'], item['sourse'], item['content'])
        self.cur.execute(insert_sql, data)
        self.conn.commit()

        return item

    def close_spider(self, spider):
        print('导入数据库完毕!!!')
        self.cur.close()
        self.conn.close()

5.settings.py文件

代码如下:

BOT_NAME = 'wangyixinwen'

SPIDER_MODULES = ['wangyixinwen.spiders']
NEWSPIDER_MODULE = 'wangyixinwen.spiders'

# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False

# 运行栏只显示错误信息,看起来比较方便清晰
LOG_LEVEL = 'ERROR'

# 打开下载中间件
DOWNLOADER_MIDDLEWARES = {
   'wangyixinwen.middlewares.WangyixinwenDownloaderMiddleware': 543,
}

# 打开管道文件
ITEM_PIPELINES = {
   'wangyixinwen.pipelines.Sqlite3Pipeline': 300,
}

6.run_spider.py文件

代码如下:

# -*- coding: utf-8 -*-
# @Time: 2020/8/18 19:01
# @Author: Ricky Rau
# @Email: 13260961739@163.com

from scrapy import cmdline

cmdline.execute('scrapy crawl wangyi'.split())

上述代码的作用和 Scrapy Shell 里的 scrapy crawl wangyi 的作用是一样,个人认为更加方便。

四、结果展示

可以下载一个DB Browser for SQLite软件,用来查阅SQLite数据库,从软件中可以清晰的看到所爬取的数据(标题,来源以及内容)。


总结

本文主要通过scrapy框架结合selenium、sqlite3对网易新闻中四大板块的标题、来源以及内容进行的爬取,过程中总会遇到大大小小的问题,有可能一个字母打错了或者一个路径写错了,都不要放弃,坚持总会有回报。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值