使用scrapy和selenium结合爬取网易新闻内容

2023-10-31

代码结构

在这里插入图片描述

相关文件的代码

爬虫文件

# mid.py 爬虫文件
import scrapy
from middle.items import MiddleItem
from selenium import webdriver


class MidSpider(scrapy.Spider):
    name = 'mid'
    start_urls = ['https://news.163.com/']

    def __init__(self):
        # 以mid.py文件取相对路径
        self.bro = webdriver.Chrome(executable_path='../chromedriver_win32/chromedriver.exe')
        self.models_url = []

    # 进行首页的数据解析,获取目标模块的超链
    def parse(self, response):
        li_list = response.xpath('//div[@class="ns_area list"]/ul/li')
        # 存放目标模块的url
        models_url = []
        # 只爬取国内、国际两个个模块
        i_list = [2, 3]
        for i in i_list:
            # 获取url和模块名称
            url = li_list[i].xpath('./a/@href').extract_first()
            model = li_list[i].xpath('./a/text()').extract_first()
            # 创建item对象并保存模块名
            item = MiddleItem()
            item['model'] = model
            # 将五个目标模块存在列表中便于下载中间件进行拦截判断
            self.models_url.append(url)
            yield scrapy.Request(url, callback=self.parse_model, meta={'item': item})

    # 进行目标模块的数据解析,获取对应标题的url
    def parse_model(self, response):
        div_list = response.xpath('//div[@class="ndi_main"]/div')
        for div in div_list:
            url = div.xpath('.//div[@class="news_title"]/h3/a/@href').extract_first()
            # 获取上一层提交过来的item进行进一步数据的保存
            item = response.meta['item']
            yield scrapy.Request(url, callback=self.parse_detail, meta={'item': item})

    # 进行对应标题页面的数据解析,获取对应的正文内容
    def parse_detail(self, response):
        title = response.xpath('//h1[@class="post_title"]/text()').extract_first()
        if title is not None:
            # 处理非法字符
            title = title.replace(' ', '').replace(':', '').replace('?', '').replace('”', '').replace('"', '').replace('?', '')
        else:
            title = '标题'
        content = response.xpath('//div[@class="post_body"]//text()').extract()
        content = '\n'.join(content)
        # 获取上一层提交过来的item进行进一步数据的保存
        item = response.meta['item']
        item['title'] = title
        item['content'] = content
        # 将item提交给管道
        yield item

    # 覆写父类方法-关闭爬虫
    def close(self, spider, reason):
        # 关闭浏览器
        self.bro.quit()

item文件

# items.py 
import scrapy


class MiddleItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # 模块名称
    model = scrapy.Field()
    # 标题名称
    title = scrapy.Field()
    # 正文内容
    content = scrapy.Field()
    pass

中间件文件(由于只使用下载中间件,所以只贴出下载中间件的代码)

# middlewares.py 中间件文件
import random
from scrapy import signals
from scrapy.http import HtmlResponse
from itemadapter import is_item, ItemAdapter
from time import sleep


class MiddleDownloaderMiddleware:
    user_agents = [
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60',
        'Opera/8.0 (Windows NT 5.1; U; en)',
        'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50',
        'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50',
        'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
        'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2 ',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36',
        'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
        'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36',
        'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER',
        'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',
        'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0',
        'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0) ',
    ]
    
    # 拦截请求
    # 一般在此处进行UA伪装
    def process_request(self, request, spider):
        # 从设置好的UA池中随机设置一个
        request.headers['User-Agent'] = random.choice(self.user_agents)
        # Must either:
        return None

    # 拦截所有响应对象
    def process_response(self, request, response, spider):
        # 获取爬虫文件中实例化的浏览器对象
        bro = spider.bro
        # 由于该方法会拦截所有响应对象,而我们需要的数据不一定是动态加载的,不需要借用selenium进行额外处理
        # 因此需要进行判断,如果没有需要的数据,再借用selenium进行处理
        # 一个request对应一个response
        # 通过spider对象可以获取爬虫文件中的成员
        if request.url in spider.models_url:
            bro.get(request.url)
            sleep(3)
            page_text = bro.page_source
            # 对需要动态加载的数据进行篡改
            # 实例化一个response对象
            new_response = HtmlResponse(url=request.url, body=page_text, encoding='utf-8', request=request)
            return new_response
        # 如果不需要篡改则返回原先的response对象
        else:
            return response

管道文件

# pipelines.py 管道文件
from itemadapter import ItemAdapter
import os


class MiddlePipeline:
    def process_item(self, item, spider):
        # 进行持久化存储
        # 以mid.py文件取相对路径
        path = '../data/'
        if not os.path.exists(path):
            os.mkdir(path)
        path += str(item['model']) + '/'
        if not os.path.exists(path):
            os.mkdir(path)
        path += str(item['title']) + '.txt'
        with open(path, 'w', encoding='utf-8') as fp:
            fp.write(str(item['content']))
        return item

设置文件

# setting.py 
# 关闭robots协议
ROBOTSTXT_OBEY = False
# 设置日志等级
LOG_LEVEL = 'ERROR'
# 打开下载中间件
DOWNLOADER_MIDDLEWARES = {
   'middle.middlewares.MiddleDownloaderMiddleware': 543,
}
# 打开管道
ITEM_PIPELINES = {
   'middle.pipelines.MiddlePipeline': 300,
}

爬取结果

在这里插入图片描述
在这里插入图片描述

注意事项

1.运行mid.py文件进行爬取时,最好到spiders文件夹的路径下进行,因为浏览器驱动的读取和数据持久化存储是按照相对路径编写的。
2.浏览器驱动的版本不一定适用,如果发现不适应,下载一个对应版本替换掉目录下的chromedriver.exe即可。
3.该用法是和某站老师学的,但是发现老师的代码是存在一些问题的,并且为了进一步练习,自己写了一份,有任何问题欢迎私聊或者评论,不定时回复。
4.完整代码如有需要个人资源自取

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用scrapy和selenium结合爬取网易新闻内容 的相关文章

随机推荐

  • Uformer: A General U-Shaped Transformer for Image Restoration阅读笔记

    Abstract 构建一个分层的编码 解码器 并使用Transformer block进行图像恢复 Uformer两个核心设计 1 local enhanced window Transformer block 使用非重叠窗口自注意力降低计
  • js 密码正则表达式(至少8位且必有数字+特殊字符+字母)

    正则 var reg A Za z d lt gt A Za z d lt gt 8 可用 test 方法验证 reg test value 参考 js正则验证特殊字符 summer7310 博客园 正则表达式 密码必须至少包含八个字符 至
  • 《人工智能》知识总结

    知识图谱表示法 1 知识图谱主要用于智能搜索 智能问答 个性化推荐 多维导航 内容分发等领域 2 语义网络更侧重于表示概念与概念之间的关系 知识图谱更侧重于表示实体与实体之间的关系 3 已有图谱作用于实体 发现 扩充新的知识图谱 4 知识图
  • Map之TreeMap

    我们先不谈TreeMap我们来直接聊聊HashMap 首先当我们用HashMap存储数据的时候 我们要如何将给出的数据排序呢 这是一个问题 那么TreeMap本身是支持排序的 是对key进行的排序 但是需要用户定义 实现排序 主要有两种方法
  • 使用智星云stable diffusion创建ai创意绘画

    目录 租赁选择 控制台 参数选择 下载图片 结束租用 租赁选择 选择完以后 下面会列出可用的显卡型号 选择对应需要的就可以 2080ti 1080ti都能跑 只不过显存越大的卡 能画的图越大 速度也越快 点击租用 用默认值即可 然后创建实例
  • 弱电人要学习的网络安全基础知识

    提到网络安全 一般人们将它看作是信息安全的一个分支 信息安全是更加广义的一个概念 防止对知识 事实 数据或能力非授权使用 误用 篡改或拒绝使用所采取的措施 说白了 信息安全就是保护敏感重要的信息不被非法访问获取 以及用来进 步做非法的事情
  • html搜索区域选择框,带搜索过滤功能的jQuery国家地区选择下拉框插件

    nicecountryinput js是一款带搜索过滤功能的jQuery国家地区选择下拉框插件 该下拉框插件通过简单的代码就可以实现所有国家和地区的选择下拉框 并且可以通过搜索框对国家地区名称进行搜索 使用方法 在页面中引入jquery m
  • ENVI 混合像元分解

    一 混合像元分解的过程 在影像已经完成预处理的前提下 如几何校正 大气校正 去噪等 混合像元分解的一般的过程 首先获取端元波谱 从图像上 波谱库中或者其他来源 然后选择一种分解模型在每个像素中获取每个端元波谱的相对丰度图 最后从丰度图上提取
  • 3. Flutter——HTTP请求

    dio数据请求 HTTP 添加依赖 dependencies dio 1 0 9 版本 get 请求 import package dio dio dart Dio dio new Dio var response await dio ge
  • Vue-element-admin在左上角添加LOGO的方法

    本文主要是分享一下思路的 如不想看可以直接跳到最后 做项目时有一个在左上角添加logo的需求 但是element admin貌似没有添加logo的位置 于是我先在页面中检查侧边栏 发现它是sidebar container类 于是我在vsc
  • eclipse中使用log4j2在控制台输出彩色日志

    目录 一 eclipse中安装Ansi Console 二 在log4j2配置文件中配置颜色样式 三 在log4j2 component properties 配置文件中启用颜色配置 四 附上log4j2配置文件 1 log4j2 xml
  • left join 连表问题解析:on后多条件无效 & where与on的区别

    在项目中用到多表联合查询 发现2个现象 今天解决这2个疑问 1 left join连接2张表 on后的条件第一个生效 用and连接的其他条件不生效 2 一旦加上where 则显示的结果等同于inner join 先写结论 过滤条件放在 wh
  • 停止一下或多个进程以继续安装 vmware-vmx.exe 问题解决

    1 起因 用vmware大虚拟机做大数据集群经常出现某个虚拟机起不来 还导致vmware无法关闭 提示某某虚拟机繁忙 经网友提示 升级到15 pro可以解决 事实证明无效 最后的解决办法是手动复制虚拟机文件 在配置文件中注释uid 然后用虚
  • Java中的多态调用问题,下面代码输出是什么?

    转自 http www lvhongqiang com blog431 html 问题 下面代码输出是什么 public class Test3 public static void main String args AAA a new B
  • Spring Boot项目中使用Logback日志与使用AOP拦截请求日志信息

    日志记录了系统行为的时间 地点等很多细节的具体信息 在发生错误或者接近某种危险状态时能够及时提醒开发人员处理 往往在系统产生问题时承担问题定位与诊断和解决的重要角色 一般很多线上的问题只能通过进行日志分析才可以解决的 所以需要明确日志在日常
  • 【Android开发,极客时间资源共享

    android divider f00 分割线的颜色 android dividerHeight 2dp 分割条的高度 android cacheColorHint 0fff 当列表使用背景图之后 下拉或者上拉都会出现一个问题 背景图不见了
  • 针对热点数据的处理

    针对热点数据的处理 出现问题 解决办法 大体思路 实现方式一 Spring Data Redis 前言 项目要求 Redis中菜品缓存数据KEY的设计 dish 分类id 一 导入依赖 二 添加缓存的代码例子 三 删除缓存 实现方式二 Sp
  • PAT : 基础编程题目集_编程题答案(7-1 ~ 7-38)(纯C编写)

    题目地址 7 1 include
  • Uncaught ReferenceError: __VUE_HMR_RUNTIME__ is not defined

    Syntax Error Error vitejs plugin vue requires vue gt 3 2 13 or vue compiler sfc to be present in the dependency tree 第一步
  • 使用scrapy和selenium结合爬取网易新闻内容

    代码结构 相关文件的代码 爬虫文件 mid py 爬虫文件 import scrapy from middle items import MiddleItem from selenium import webdriver class Mid