scrapy分页抓取网页(用Scrapy写爬虫再只要理清下面两点就能写成一个 )

优采云 发布时间: 2021-11-15 04:04

  scrapy分页抓取网页(用Scrapy写爬虫再只要理清下面两点就能写成一个

)

  1 简介

  Scrapy模块中有4个现成的蜘蛛类,分别是:

  SpiderCrawlSpiderXMLFeedSpiderCSVFeedSpider

  Spider是最简单的爬虫,也是最基本的爬虫。包括自定义爬虫在内的所有其他爬虫都必须继承它。本节主要讲Scrapy编写爬虫的核心内容,从CrawlSpider类开始,开始学习如何搭建最简单的爬虫程序。

  在我写的第一篇文章中,我说爬虫无非是以下几点:

  请求(requests)目标站点的网页(文本);使用正则表达式、Beautiful Soup、LXML、CSS 提取数据;制定爬取规则(如“下一页”等)、爬取方式(异步爬取、设置代理等);存储数据。

  至于如何存储数据,我们暂时不关心,因为在Scrapy的命令行中,可以通过参数直接将数据存储到文件中,见【命令行工具】-命令行工具。

  总结我以往的经验,用Scrapy写爬虫,只要搞清楚以下两点就可以写成爬虫了:

  知道要爬哪些页面,爬完这个页面后要爬哪些页面,入口点在哪里;如何从这些页面中提取数据

  对于第二点,我们在最近的3次文章中已经做了详细的介绍。这里我就不多说了。学习完本节内容后,您可以进一步了解提取数据的方法:

  [Easy XPath]-开始使用XPath

  [RegEx]-正则表达式

  【Scrapy中的选择器】-数据匹配方法

  因此,本节将带您从示例中阐明编写爬虫的思路和方法。

  2 需求分析

  假设你目前不清楚如何用Scrapy写爬虫,那么你手头只有一个任务,就是你要爬取哪些数据网站。所以第一步就是分析需求,搞清楚爬取的顺序,其他的就别管了。

  任务:

  爬取->网站 热门标签下的所有引用及其作者

  看看这个页面:

  scrapy view http://quotes.toscrape.com/

  

  图片右侧的红框是热门标签。让我们随机点击一个标签来签到:

  http://quotes.toscrape.com/tag/love/

  

  我们将上图定义为标签主页,上图中的红框代表我们需要提取的数据项。在数据爬取中,我们必须最大程度的保证数据的完整性,也就是说:获取所有存在于网站上的目标数据。除了标签首页的数据,剩下的数据在哪里?入口在哪里?

  往下我们找到Next按钮,打开调试器查看它的地址:

  http://quotes.toscrape.com/tag/love/page/2/

  

  点击第二页,已经找不到Next按钮了,也就是love标签下的数据只存在于两个页面:

  http://quotes.toscrape.com/tag/love/

http://quotes.toscrape.com/tag/love/page/2/

  

  总结两个步骤:

  ① 获取首页右侧所有热门标签对应的地址:

  http://quotes.toscrape.com/tag/love/

http://quotes.toscrape.com/tag/inspirational/

……

  ② 访问各标签首页,在各标签首页点击“下一步”获取剩余数据,直到找不到下一步按钮

  最后再补充一点:

  爱标签首页的数据,分析起来,是第一页。这是否意味着它相当于:

  http://quotes.toscrape.com/tag/love/page/1/

  我们在标签主页上找到了这个链接:

  

  因此,可以按以下顺序获取每个标签下的数据:

  http://quotes.toscrape.com/tag/love/page/1/

http://quotes.toscrape.com/tag/love/page/2/

……

  这是第一点:

  下面两个网站指向同一个页面:

  http://quotes.toscrape.com/tag/love/

http://quotes.toscrape.com/tag/love/page/1/

  如果我们按照上面的页数抓取数据,那么我们的数据就是重复的。我们需要在下面进一步解决这个问题。

  3 CrawlSpider类使用详解

  先通风一下它独特的属性和方法,然后就从刚刚完成上述任务开始,给爬虫代码,写下CrawlSpider类中各个参数用法的例子。

  ① parse_start_url(response)

  用于处理start_urls的响应,它的用处是:如果需要模拟登录等操作,可以重写这个方法。

  ② Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None)

  规则用于:

  以指定格式提取链接(link_extractor);过滤提取的链接(process_links);为指定页面指定相应的处理方法(process_request);指定页面的处理方式(回调);为不同的提取链接方法指定后续规则(Follow);将参数 (cb_kwargs) 传递给回调函数。

  避免使用 parse 作为回调函数(callback)

  在 PyCharm 中创建文件如下:

  

  env:虚拟环境

simple:爬虫文件夹

Quotes_CrawlSpider.py:爬虫

run.py:用于启动爬虫,方便调试

  run.py的代码如下:

  from scrapy import cmdline

cmdline.execute("scrapy runspider Quotes_CrawlSpider.py -o quotes.json".split())

  解释:

  相当于从命令行启动爬虫文件,-oquotes.json将爬虫产生的item保存到json文件中。

  3.1 完成上述爬虫任务所需的爬虫代码

  Quotes_CrawlSpider.py 的代码如下:

  # -*- coding: utf-8 -*-

from scrapy.spiders import CrawlSpider, Rule

from scrapy.linkextractors import LinkExtractor

class MySpider(CrawlSpider):

name = 'toscrape.com'

allowed_domains = ['toscrape.com']

start_urls = ['http://quotes.toscrape.com/']

rules = (

Rule(LinkExtractor(allow=('/tag/\w+/$',)),

follow=True, # 如果有指定回调函数,默认不跟进

callback='parse_item',

process_links='process_links',),

Rule(LinkExtractor(allow=('/tag/\w+/page/\d+/',), deny=('/tag/\w+/page/1/',)),

callback='parse_item',

follow=True,),

)

@staticmethod

def process_links(links): # 对提取到的链接进行处理

for link in links:

link.url = link.url + 'page/1/'

yield link

@staticmethod

def parse_item(response): # 解析网页数据并返回数据字典

quote_block = response.css('div.quote')

for quote in quote_block:

text = quote.css('span.text::text').extract_first()

author = quote.xpath('span/small/text()').extract_first()

item = dict(text=text, author=author)

yield item

  流程图:

  

  详细代码:

  提取规则1:(①-④)

  Rule(LinkExtractor(allow=('/tag/\w+/$',)), # 从主页提取标签主页的地址,利用正则表达式

follow=True, # request标签主页得到内容,继续在该内容上上应用规则提取链接

callback='parse_item', # request标签主页得到内容,对该内容应用parse_item函数提取数据

process_links='process_links',), # 用process_links方法对提取到的链接做处理,将标签主页变成/page/1/形式

  提取规则2:(⑤,⑥)

  Rule(LinkExtractor(allow=('/tag/\w+/page/\d+/',), deny=('/tag/\w+/page/1/',)),

# 提取链接格式满足“/tag/英文字母/page/”数字/形式的,并拒绝第一页

callback='parse_item', # 指定parse_item作为页面的处理方法

follow=True,), # 需要在得到的页面继续搜索满足规则的链接

  parse_start_url(响应)

  from scrapy.spiders import CrawlSpider

class QuotesSpider(CrawlSpider):

name = "quotes"

custom_settings = {

'LOG_LEVEL': 'INFO',

}

start_urls = ['http://quotes.toscrape.com/tag/love/']

def parse_start_url(self, response):

self.logger.info('parse_start_url %s', response.url)

next_page = response.css('li.next a::attr("href")').extract_first()

if next_page is not None:

yield response.follow(next_page, self.next_parse)

def next_parse(self, response):

self.logger.info('next_pares %s', response.url)

  rule的几个参数用法示例:

  # -*- coding: utf-8 -*-

from scrapy.spiders import CrawlSpider, Rule

from scrapy.linkextractors import LinkExtractor

class MySpider(CrawlSpider):

name = 'toscrape.com'

custom_settings = {

'LOG_LEVEL': 'INFO', # 设置日志级别

}

allowed_domains = ['toscrape.com']

start_urls = ['http://quotes.toscrape.com/']

rules = (

Rule(LinkExtractor(allow=('/tag/\w+/$',)),

follow=False, # 为了测试几个参数的用法简单设定

callback='parse_item',

cb_kwargs={'tag': 'love'}, # 以key名tag作为变量名传给回调函数parse_item

process_links='process_links', # 对提取的链接做处理

process_request='process_req' # 对每个请求做处理),

)

@staticmethod

def process_links(links):

for link in links:

link.url = link.url + 'page/1/'

yield link

def process_req(self, req):

if 'love' in req.url: # 我们测试当链接中包含love是转给parse_love处理response

return req.replace(callback=self.parse_love)

elif 'humor' in req.url:

return req # 如果链接中包含humor则正常用回调函数parse_item处理response

def parse_love(self, response):

self.logger.info('parse_love %s' % response.url)

def parse_item(self, response, tag):

self.logger.info('parse_item %s' % response.url)

self.logger.info('not %s' % tag)

  操作结果:

  

  操作流程:

  

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线