当前位置:   article > 正文

Scrapy爬虫框架

scrapy爬虫框架

十三周内容笔记

day37

01-selenium相关配置

封装到一起用的时候调用就可以了,很方便。

def self_options():
    op = webdriver.ChromeOptions()
    # 1. 设置selenium不自动关闭浏览器
    op.add_experimental_option("detach", True)
    # 2. 不加载网页图片,提升网页加载速度
    op.add_argument('blink-settings=imagesEnabled=false')
    # 3. 避免终端下执行代码报错
    op.add_experimental_option("excludeSwitches", ['enable-automation', 'enable-logging'])
    # 4. 为selenium设置请求头UA,selenium调用的浏览器自带UA,但是因为存在UA反爬,所以可以选择性是否添加
    UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
    op.add_argument(f"--user-agent={UA}")
    # 5. 设置代理IP
    # proxy_ip = '127.0.0.1:8000'
    # op.add_argument(f'--proxy-server=http://{proxy_ip}')
    # 6. 加载拓展插件
    op.add_extension('./FeHelper.crx')
    # 7. 加载用户缓存,可以记录使用记录和cookie,如果不指定缓存路径,会自动创建临时文件夹。
    # user_dir = r'./browser_cache'
    # op.add_argument(f"--user-data-dir={user_dir}")
    # 8. 无头浏览器:提升网页访问速度,但是牺牲的是增加更多的反爬风险,如果涉及到与网页的交互,有些网站就不能使用无头模式。
    op.add_argument('--headless')
    return op
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

02-selenium窗口尺寸对爬虫的影响

如果窗口过小,会导致selenium无法实现下一步的操作,页面上不显示,自然就无法找到对应的位置进行交互,会返回element click intercepted

element click intercepted:有些网站有检测机制,页面元素未显示在用户视野中(网页显示区域)时,元素不允许进行交互。

browser.maximize_window():窗口最大化

03-爬虫蜜罐

蜜罐:形容抵不住诱惑,之前在学习网安的时候了解到过。爬虫蜜罐即爬虫陷阱。

一、概述

一个接入了互联网的网站,只要能和外部产生通信,就有可能被黑客攻击。所以有些网站设置了一些陷阱,来引诱攻击者从而达到自身不被攻击的目的。

二、蜜罐分类

电子邮件蜜罐:邮箱管理者会在网络中故意放出一些邮箱账号,这些账号只能被扫描器发现,正常人发现不了,所以如果这些账号接收到邮件,就可以将发件地址标记为恶意账号。

数据库蜜罐:用来监控攻击者对数据库的攻击命令或发现利用sql注入攻击,运营人员就可以将访问数据区的ip地址拉黑。

爬虫蜜罐:例如:在网页源码中注释掉一些链接,这些链接普通用户永远不会看到,但是写爬虫的人能看到,爬虫能访问到,如果有爬虫访问了这些注释掉的陷阱链接,立刻能够检测到是哪个ip地址访问了,直接将此ip拉黑。

三、蜜罐的优缺点

优点:节省资源、能够轻易捕捉到危险、准确率高。

缺点:准确率高不等于100%,有误封的缺点。

day38

scrapy爬虫框架

一、scrapy爬虫框架介绍

scrapy是基于python开发的爬虫框架,用于从网站中抓取数据。python爬虫领域中scrapy是最强悍的框架。该框架提供了非常多的爬虫相关的基础组件,建构清晰,可拓展性强。
在这里插入图片描述

二、scrapy爬虫框架出现的条件

每次写爬虫都需要写一遍重复性的内容,scrapy作者就根据重复性的内容封装成通用的代码,通过多版本迭代,住家形成规模庞大的框架。

三、安装

pip install scrapy

四、创建scrapy爬虫项目

命令:scrapy startproject 项目名

创建中国新闻网爬虫项目:scrapy startproject ChinaNews

创建完是这样式儿的:

sc
后面会对上面的文件展开操作

五、开始操作

先使用cd命令切换进项目,通过命令初始化某个网站的爬虫文件

scrapy genspider 文件名(运行scrapy项目时的名字)被爬取网站的链接

scrapy genspider NewsSpider https://www.chinanews.com.cn/

六、scrapy爬虫项目的运行

scrapy crawl 爬虫名字

scrapy crawl NewsSpider

七、settings.py(很重要)

这是scrapy的配置文件,需要修改成不遵循robots协议:ROBOTSTXT_OBEY = False

在这里插入图片描述

在这里插入图片描述

八、多线程(默认16线程):

在这里插入图片描述

day39

对中国新闻网即时新闻精选进行实操

一、在NewsSpider.py文件内写爬虫代码

在这里插入图片描述

import scrapy
from ..items import ChinanewsItem
class NewsspiderSpider(scrapy.Spider):
    name = "NewsSpider"
    allowed_domains = ["www.chinanews.com.cn"]
    start_urls = ["https://www.chinanews.com.cn/"]

    def parse(self, response):
        # response:网页的响应结果
        # 查看网页源代码
        # print(response.text)
        # css方法:scrapy提供了css方法能够使用css选择器定位到元素
        # 如果要取标签属性,需要在css方法的css选择器中这样写 --> 标签::attr(属性名)
        # get():获取到css选择器指定的内容
        link = response.css('body > div:nth-child(9) > div.news-right > div.top-jsxw > div.jsxw-title.lmtitle > a::attr(href)').get()
        # print(link)
        # 将链接补全
        new_link = self.start_urls[0] + link[1:]
        # print(new_link)
        # 构建10页链接
        for page in range(1, 11):
            page_link = new_link.replace('1', str(page))
            # print(page_link)
            # scrapy.Request():scrapy中负责请求链接的方法
            # callback:回调函数,可以提前调用一个不存在的函数、变量等,然后紧接着再去创建。
            yield scrapy.Request(url=page_link, callback=self.NewsInfo)

    # Xpath写法
    def NewsInfo(self, response):
        # 实例化实体类
        newsItem = ChinanewsItem()

        # 此时response根节点时html
        li_list = response.xpath('/html/body/div[4]/div[1]/div[2]/ul/li')
        for i in li_list:
            if i.xpath('./@class').get() != 'nocontent':
                news_type = i.xpath('./div[1]/a/text()').get()
                news_title = i.xpath('./div[2]/a/text()').get()
                news_link = 'https://www.chinanews.com.cn' + i.xpath('./div[2]/a/@href').get()
                news_time = i.xpath('./div[3]/text()').get()
                # print(news_type, news_title, news_link, news_time)
                newsItem['NewsType'] = news_type
                newsItem['NewsTitle'] = news_title
                newsItem['NewsLink'] = news_link
                newsItem['NewsTime'] = news_time
                yield newsItem
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

还有CSS写法,不过我不太喜欢CSS,看起来代码太臃肿。

    # CSS选择器写法
    def NewsInfo(self, response):
        # 从响应结果中查看访问的是哪个链接
        # print(response.url)
        # 获取当前页面的所有新闻的li标签
        li_list = response.css('body > div.w1280.mt20 > div.content-left > div.content_list > ul > li')
        # print(li_list)
        for i in li_list:
            # 如果要取标签内容,需要在css方法的css选择器中这样写 --> 标签::text
            news_type = i.css('li > div.dd_lm > a::text').get()
            # 如果li的class属性为nocontent,即值为空,则去掉此li标签
            if news_type != None:
                news_title = i.css('li > div.dd_bt > a::text').get()
                news_link = 'https://www.chinanews.com.cn' + i.css('li > div.dd_bt > a::attr(href)').get()
                news_time = i.css('li > div.dd_time::text').get()
                print(news_type, news_title, news_link, news_time)
                newsItem['NewsType'] = news_type
                newsItem['NewsTitle'] = news_title
                newsItem['NewsLink'] = news_link
                newsItem['NewsTime'] = news_time
                yield newsItem
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

二、在items.py文件内实体化

import scrapy

class ChinanewsItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # 此处写什么代码取决于你提取了哪些信息
    NewsType = scrapy.Field()
    NewsTitle = scrapy.Field()
    NewsLink = scrapy.Field()
    NewsTime = scrapy.Field()
    # Field()是获取scrapy提供的Item类(实体类)中的信息

    # 爬虫主要目标就是从非结构化数据源中提取出结构化的数据
    # 结构化数据一般是一个字段对应一个或一类数据,这种情况下字典是最好用的
    # 但是字典很容易将键的名字写错,此时scrapy的Item类起作用了,Item类本身就是处理结构化数据的
    # 将字段名化为变量名使用,就不会出错了。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

三、数据存储,在piplines.py内操作

在这里插入图片描述

import csv
# scrapy 的数据存储有两种形式
# 方式一:直接使用命令存储文件
# scrapy crawl 爬虫名字 -o 文件名.拓展名
# 或者 scrapy crawl 爬虫名字 --output 文件名.拓展名
# 使用命令的形式存储数据,拓展名支持8种类型的文件
# json、jsonlines、jsonl、jl、csv、xml、marshal、pickel(python 高性能文件)
# scrapy crawl NewsSpider -o data.csv

# 方式二:手写代码实现数据的存储
# 注意:管道中的代码想要执行,必须告知scrapy,我添加了什么代码
class ChinanewsPipeline:
    def process_item(self, item, spider):
        return item

class ChinanewsToCsvPipline:
    def open_spider(self, spider):
        """当爬虫开始执行时,open_spider被执行"""
        self.file = open('数据.csv', 'w', encoding='utf-8', newline='')
        csv.writer(self.file).writerow(['新闻类型', '新闻标题', '新闻链接', '发布时间'])

    def process_item(self, item, spider):
        """爬虫执行过程中执行的代码"""
        data = [item['NewsType'], item['NewsTitle'], item['NewsLink'], item['NewsTime']]
        csv.writer(self.file).writerow(data)
        return item

    def close_spider(self, spider):
        """当爬虫结束执行时,close_spider被执行"""
        self.file.close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

管道中的代码想要执行,必须告知scrapy,我添加了什么代码,在settings.py中操作

在这里插入图片描述

# 字典中的键是管道中需要执行的代码,对应的数值是执行的先后顺序,范围[0, 1000]
# 数值越小,优先级越高
ITEM_PIPELINES = {
   # "ChinaNews.pipelines.ChinanewsPipeline": 300,
   "ChinaNews.pipelines.ChinanewsToCsvPipline": 300,
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

四、UA反反爬的设置

在middlewares.py文件中操作,添加如下类

在这里插入图片描述

class ChinanewsUserAgentDownloaderMiddleware:

    def __init__(self):
        file = open('UserAgent.txt', 'r')
        self.UAList = ast.literal_eval(file.read())

    @classmethod
    def from_crawler(cls, crawler):
        """在爬虫开始或结束时进行一些操作的函数"""
        # This method is used by Scrapy to create your spiders.
        s = cls()
        crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
        return s

    def process_request(self, request, spider):
        """下载器发送请求前针对请求的处理"""
        # 将一个UA放入到请求的headers中
        request.headers['User-Agent'] = random.choice(self.UAList)
        return None

    def process_response(self, request, response, spider):
        """下载器请求完页面,和引擎通信时对响应结果做的处理"""
        return response

    def process_exception(self, request, exception, spider):
        """如果出现异常,怎么处理"""
        pass

    def spider_opened(self, spider):
        """日志信息处理"""
        spider.logger.info("Spider opened: %s" % spider.name)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

同样需要告诉scrapy我添加了什么代码

在这里插入图片描述

DOWNLOADER_MIDDLEWARES = {
   # "ChinaNews.middlewares.ChinanewsDownloaderMiddleware": 543,
   "ChinaNews.middlewares.ChinanewsUserAgentDownloaderMiddleware": 100,
}
  • 1
  • 2
  • 3
  • 4

这玩意儿是真有点抽象,要完全理解需要时间的,不过我觉得现在刚刚起步,不着急理解的,先依葫芦画瓢当个工具使用就就可以,毕竟用工具的时候不会有人会去完全弄清楚原理吧哈哈。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/599627
推荐阅读
相关标签
  

闽ICP备14008679号