系列文章目录
文章目录
前言
摘录自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,
}
总结:
需要使用 LinkExtractor
和 Rule
。这两个东西决定爬虫的具体走向。
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。