5.2-python爬虫之CrawlSpider&Scrapy Shell&Request和Response对象

系列文章目录

python爬虫目录



前言

摘录自B站对应课程笔记
不愧是清华大佬!把Python网络爬虫讲得如此简单明了!从入门到精通保姆级教程(建议收藏)

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


一、CrawlSpider爬虫

在上一个糗事百科的爬虫案例中。我们是自己在解析完整个页面后获取下一页的url,然后重新发送一个请求。有时候我们想要这样做,只要满足某个条件的url,都给我进行爬取。那么这时候我们就可以通过CrawlSpider来帮我们完成了。CrawlSpider继承自Spider,只不过是在之前的基础之上增加了新的功能,可以定义爬取的url的规则,以后scrapy碰到满足条件的url都进行爬取,而不用手动的yield Request。

1、创建CrawlSpider爬虫

之前创建爬虫的方式是通过scrapy genspider [爬虫名字] [域名]的方式创建的。如果想要创建CrawlSpider爬虫,那么应该通过以下命令创建:

scrapy genspider -t crawl [爬虫名字] [域名]

2、LinkExtractors链接提取器

使用LinkExtractors可以不用程序员自己提取想要的url,然后发送请求。这些工作都可以交给LinkExtractors,他会在所有爬的页面中找到满足规则的url,实现自动的爬取。以下对LinkExtractors类做一个简单的介绍:

class scrapy.linkextractors.LinkExtractor(
    allow = (),
    deny = (),
    allow_domains = (),
    deny_domains = (),
    deny_extensions = None,
    restrict_xpaths = (),
    tags = ('a','area'),
    attrs = ('href'),
    canonicalize = True,
    unique = True,
    process_value = None
)

主要参数讲解:

allow:允许的url。所有满足这个正则表达式的url都会被提取。
deny:禁止的url。所有满足这个正则表达式的url都不会被提取。
allow_domains:允许的域名。只有在这个里面指定的域名的url才会被提取。
deny_domains:禁止的域名。所有在这个里面指定的域名的url都不会被提取。
restrict_xpaths:严格的xpath。和allow共同过滤链接。

3、Rule规则类

定义爬虫的规则类。以下对这个类做一个简单的介绍:

class scrapy.spiders.Rule(
    link_extractor, 
    callback = None, 
    cb_kwargs = None, 
    follow = None, 
    process_links = None, 
    process_request = None
)

主要参数讲解:

  • link_extractor:一个LinkExtractor对象,用于定义爬取规则。
  • callback:满足这个规则的url,应该要执行哪个回调函数。因为CrawlSpider使用了parse作为回调函数,因此不要覆盖parse作为回调函数自己的回调函数。
  • follow:指定根据该规则从response中提取的链接是否需要跟进。
  • process_links:从link_extractor中获取到链接后会传递给这个函数,用来过滤不需要爬取的链接。

4、微信小程序社区CrawlSpider案例

文件结构
在这里插入图片描述
wxapp_spider.py

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from wxapp.items import WxappItem
 
class WxappSpiderSpider(CrawlSpider):
    name = 'wxapp_spider'
    allowed_domains = ['wxapp-union.com']
    start_urls = ['https://www.wxapp-union.com/portal.php?mod=list&catid=2&page=1']
 
    rules = (
        Rule(LinkExtractor(allow=r'.+mod=list&catid=2&page=\d'), follow=True),
        Rule(LinkExtractor(allow=r".+article-.+\.html"), callback="parse_detail", follow=False)
    )
 
    def parse_detail(self, response):
        # 从页面提取数据
        title = response.xpath("//h1[@class='ph']/text()").get()
        authors_p = response.xpath("//p[@class='authors']")
        author = authors_p.xpath("./a/text()").get()
        pub_time = authors_p.xpath("./span/text()").get()
        content = response.xpath("//td[@id='article_content']//text()").getall()
        content = "".join(content).strip()
        # 使用 items.py 下的 WxappItem 类封装数据
        item = WxappItem(title=title, author=author, pub_time=pub_time, content=content)
        return item

items.py

import scrapy
 
class WxappItem(scrapy.Item):
    title = scrapy.Field()
    author = scrapy.Field()
    pub_time = scrapy.Field()
    content = scrapy.Field()

pipelines.py

from itemadapter import ItemAdapter
from scrapy.exporters import JsonLinesItemExporter
 
 
class WxappPipeline:
    def __init__(self):
        self.fp = open("wxapp.json", "wb")
        self.exporter = JsonLinesItemExporter(self.fp, encoding="utf-8", ensure_ascii=False)
 
    def process_item(self, item, spider):
        self.exporter.export_item(item)
        return item
 
    def close_spider(self, spider):
        print("准备关闭")
        self.fp.close()

** setting.py**

BOT_NAME = 'wxapp'
 
SPIDER_MODULES = ['wxapp.spiders']
NEWSPIDER_MODULE = 'wxapp.spiders'
 
ROBOTSTXT_OBEY = False
 
DOWNLOAD_DELAY = 1
 
DEFAULT_REQUEST_HEADERS = {
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36",
}
 
ITEM_PIPELINES = {
   'wxapp.pipelines.WxappPipeline': 300,
}
 

总结:
需要使用 LinkExtractorRule。这两个东西决定爬虫的具体走向。

1、allow 设置规则的方法:要能够限制在我们想要的 url 上面。不要跟其他的 url 产生相同的正则表达式即可。
2、什么情况下使用 follow:如果在爬取页面的时候,需要将满足当前条件的 url 再进行跟进,那么就设置为 True, 否则设置为 False
3、什么情况下该指定 callback : 如果这个 url 对应的页面,只是为了获得更多的url,并不需要里面的数据,那么可以不指定 callback。如果想要获取 url 对应页面中的数据,那么就需要指定一个 callback。

二、Scrapy Shell

我们想要在爬虫中使用xpath、beautifulsoup、正则表达式、css选择器等来提取想要的数据。但是因为scrapy是一个比较重的框架。每次运行起来都要等待一段时间。因此要去验证我们写的提取规则是否正确,是一个比较麻烦的事情。因此Scrapy提供了一个shell,用来方便的测试规则。当然也不仅仅局限于这一个功能。

1、打开Scrapy Shell

打开cmd终端,进入到Scrapy项目所在的目录,然后进入到scrapy框架所在的虚拟环境中,输入命令scrapy shell [链接]。就会进入到scrapy的shell环境中。在这个环境中,你可以跟在爬虫的parse方法中一样使用了。
在这里插入图片描述

查询获取到的网页信息:
在这里插入图片描述

总结:
1、可以方便我们做一些数据提取的测试代码
2、如果想要执行scrapy 命令, 那么肯定要先进入到 scrapy 所在的环境中。
3、如果想要读取某个项目的配置信息,那么应该先进入到项目中,再执行 scrapy shell 命令。

三、Request和Response对象

1、Request 对象

Request 类初始化代码

class Request(object_ref):
 
    def __init__(self, url, callback=None, method='GET', headers=None, body=None,
                 cookies=None, meta=None, encoding='utf-8', priority=0,
                 dont_filter=False, errback=None, flags=None, cb_kwargs=None):
 
        self._encoding = encoding  # this one has to be set first
        self.method = str(method).upper()
        self._set_url(url)
        self._set_body(body)
        if not isinstance(priority, int):
            raise TypeError(f"Request priority not an integer: {priority!r}")
        self.priority = priority
 
        if callback is not None and not callable(callback):
            raise TypeError(f'callback must be a callable, got {type(callback).__name__}')
        if errback is not None and not callable(errback):
            raise TypeError(f'errback must be a callable, got {type(errback).__name__}')
        self.callback = callback
        self.errback = errback
 
        self.cookies = cookies or {}
        self.headers = Headers(headers or {}, encoding=encoding)
        self.dont_filter = dont_filter
 
        self._meta = dict(meta) if meta else None
        self._cb_kwargs = dict(cb_kwargs) if cb_kwargs else None
        self.flags = [] if flags is None else list(flags)

Request 对象在我们写爬虫,爬取一页的数据需要重新发送一个请求的时候调用。这个类需要传递一些参数,其中比较常用的参数有:
1、url: 这个 request 对象发送请求的 url.
2、callback:在下载器下载完相应的数据后执行的回调函数。
3、method:请求的方法。默认为 get 方法, 可以设置为其他方法。
4、headers : 请求头, 对于一些固定的设置,放在 setting.py 中指定就可以了。对于那些非固定的,可以在发送请求的时候指定。
5、meta: 比较常用。用于在不同的请求之间传递数据用的。
6、encoding:编码。默认的为 utf-8, 使用默认的就可以了。
7、dot_filter:表示不由调度器过滤。在执行多次重复的请求的时候,用的比较多。
8、errback:在发送错误的时候执行的函数。

2、Resqonse 对象

Response 对象初始代码

class Response(object_ref):
 
    def __init__(self, url, status=200, headers=None, body=b"", flags=None,
        request=None, certificate=None, ip_address=None, protocol=None,):
 
        self.headers = Headers(headers or {})
        self.status = int(status)
        self._set_body(body)
        self._set_url(url)
        self.request = request
        self.flags = [] if flags is None else list(flags)
        self.certificate = certificate
        self.ip_address = ip_address
        self.protocol = protocol

Resqonse 对象一般是由 Scrapy 给你自动构建的。因此开发者不需要关心如何创建 Resqonse 对象,而是如何使用它。Response 对象有很多属性,可以用来提取数据的。主要有以下的属性:
1、meta:从其他请求传递过来的 meta 属性,可以用来保持多个请求之间的数据链接。
2、encoding:返回当前字符串编码和解码的格式。
3、text:将返回来的数据为 unicode 字符串返回。
4、body:将返回来的数据作为 bytes 字符串返回。
5、xpath: xpath 选择器。
6、css: css选择器

3、发送 POST 请求

有时候我们想要在请求数据的时候发送post请求,那么这时候需要使用 Request 的子类 formRequest 来实现。

使用 formRequest 发送请求时,如果没有指定 callback 方法,那么默认会调用 parse 方法,所以一般如果不需要回调,那么指定一个空方法。

如果想要在爬虫一开始的时候就发送 POST 请求,那么需要在爬虫类中重写 start_requests(self) 方法,并且不再调用 start_urls 里的 url。

4、模拟登陆

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nosimper

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值