(4)分布式下的爬虫Scrapy应该如何做-规则自动爬取及命令行下传参

本次探讨的主题是规则爬取的实现及命令行下的自定义参数的传递,规则下的爬虫在我看来才是真正意义上的爬虫。

我们选从逻辑上来看,这种爬虫是如何工作的:

我们给定一个起点的url link ,进入页面之后提取所有的ur 链接,我们定义一个规则,根据规则(用正则表达式来限制)来提取我们想要的连接形式,然后爬取这些页面,进行一步的处理(数据提取或者其它动作),然后循环上述操作,直到停止,这个时候有一个潜在的问题,就是重复爬取,在scrapy 的框架下已经着手处理了这些问题,一般来说,对于爬取过滤的问题,通用的处理方式是建立一个地址表,在爬取之前查一下这个地址表,是否已经爬取过,如果是,则直接过滤掉。另一种就是使用现成的通用解决方案,bloom filter

本次讨论的是如何使用CrawlSpider 来进行爬取豆瓣标签下的所有小组的信息:

一,我们新建立一个类,继承自CrawlSpider

from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from douban.items import GroupInfo

class MySpider(CrawlSpider):

关于CrawlSpider的更多说明,请参考:http://doc.scrapy.org/en/latest/topics/spiders.html#crawlspider

二,为了完成命令行下的参数传递,我们需要在类的构造函数里面输入我们想要的参数

在命令行下这样使用:

scrapy crawl douban.xp --logfile=test.log  -a target=%E6%96%87%E5%85%B7

这样就可以将自定义的参数传入到里面

这里特别说明最后的一行:super(MySpider, self).__init__()

我们转到定义,查看CrawlSpider 的定义:

构造函数会调用私有方法编译rules变量,如果在我们自己定义的Spider里面没有调用方法,会直接报错的。

三,编写规则:

     self.rules = (
            Rule(LinkExtractor(allow=(‘/group/explore[?]start=.*?[&]tag=.*?$‘, ), restrict_xpaths=(‘//span[@class="next"]‘)), callback=‘parse_next_page‘,follow=True),
            )

allow 定义想要提取标签样式,使用正则匹配,restrict_xpaths 严格限制这种标签的范围在指定的标签内,callback ,提取到之后的回调函数。

四,全部代码参考:

from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from douban.items import GroupInfo

class MySpider(CrawlSpider):
    name = ‘douban.xp‘
    current = ‘‘
    allowed_domains = [‘douban.com‘]
    def __init__(self, target=None):
        if self.current is not ‘‘:
            target = self.current
        if target is not None:
            self.current = target
        self.start_urls = [
                ‘http://www.douban.com/group/explore?tag=%s‘ % (target)
            ]
        self.rules = (
            Rule(LinkExtractor(allow=(‘/group/explore[?]start=.*?[&]tag=.*?$‘, ), restrict_xpaths=(‘//span[@class="next"]‘)), callback=‘parse_next_page‘,follow=True),
            )
        #call the father base function
        super(MySpider, self).__init__()       

    def parse_next_page(self, response):
        self.logger.info(msg=‘begin init the page %s ‘ % response.url)
        list_item = response.xpath(‘//a[@class="nbg"]‘)

        #check the group is not null
        if list_item is None:
            self.logger.info(msg=‘cant select anything in selector ‘)
            return
        for a_item in list_item:
            item = GroupInfo()
            item[‘group_url‘] = ‘‘.join(a_item.xpath(‘@href‘).extract())
            item[‘group_tag‘] = self.current
            item[‘group_name‘] = ‘‘.join(a_item.xpath(‘@title‘).extract())
            yield item

    def parse_start_url(self, response):
        self.logger.info(msg=‘begin init the start page %s ‘ % response.url)
        list_item = response.xpath(‘//a[@class="nbg"]‘)

        #check the group is not null
        if list_item is None:
            self.logger.info(msg=‘cant select anything in selector ‘)
            return
        for a_item in list_item:
            item = GroupInfo()
            item[‘group_url‘] = ‘‘.join(a_item.xpath(‘@href‘).extract())
            item[‘group_tag‘] = self.current
            item[‘group_name‘] = ‘‘.join(a_item.xpath(‘@title‘).extract())
            yield item

    def parse_next_page_people(self, response):
        self.logger.info(‘Hi, this is an the next page! %s‘, response.url)

五,实际运行:

scrapy crawl douban.xp --logfile=test.log  -a target=%E6%96%87%E5%85%B7

实际的数据效果:

本次主要解决两个问题:

1.如何从命令行下传递参考

2.如何编写CrawlSpider

里面的演示的功能都比较有限,实际的运行中其实是需要进一步编写其它的规则,比如如何防止被ban,下一篇在简短的介绍下

时间: 2024-08-03 07:55:47

(4)分布式下的爬虫Scrapy应该如何做-规则自动爬取及命令行下传参的相关文章

(9)分布式下的爬虫Scrapy应该如何做-关于ajax抓取的处理(一)

转载请注明出处:http://www.cnblogs.com/codefish/p/4993809.html 最近在群里频繁的被问到ajax和js的处理问题,我们都知道,现在很多的页面都是用动态加载的技术,这一方面带来了良好的页面体验,另一方面,在抓取时或者或少的带来了相当大的麻烦,因为我们知道直接get主页页面url,这些内容是没有办法显示的.那怎么处理这些内容呢? 上图是一个直观的分析,在抓取数据时,我们一般优先考虑到手机端的网站,因为手机端的网站得到数据相对容易,特别是wap协议的网站,其

(8)分布式下的爬虫Scrapy应该如何做-图片下载(源码放送)

  转载主注明出处:http://www.cnblogs.com/codefish/p/4968260.html 在爬虫中,我们遇到比较多需求就是文件下载以及图片下载,在其它的语言或者框架中,我们可能在经过数据筛选,然后异步的使用文件下载类来达到目的,Scrapy框架中本身已经实现了文件及图片下载的文件,相当的方便,只要几行代码,就可以轻松的搞定下载.下面我将演示如何使用scrapy下载豆瓣的相册首页内容. 优点介绍: 1)自动去重 2)异步操作,不会阻塞 3)可以生成指定尺寸的缩略图 4)计算

(1)分布式下的爬虫Scrapy应该如何做-安装

关于Scrapy的安装,网上一搜一大把,一个一个的安装说实话是有点麻烦,那有没有一键安装的?答案显然是有的,下面就是给神器的介绍: 主页:http://conda.pydata.org/docs/ 下载地址:http://continuum.io/downloads 两个版本,64位和32位,根据自己的系统下载 下载之后一键安装,安装完之后以管理员身份运行CMD 输入下列命令: conda install scrapy 出现对话是否安装,输入Y 吃吃薯片,看看毛片,等着安装完就好了.完了之后就可

python网络爬虫之使用scrapy自动爬取多个网页

前面介绍的scrapy爬虫只能爬取单个网页.如果我们想爬取多个网页.比如网上的小说该如何如何操作呢.比如下面的这样的结构.是小说的第一篇.可以点击返回目录还是下一页 对应的网页代码: 我们再看进入后面章节的网页,可以看到增加了上一页 对应的网页代码: 通过对比上面的网页代码可以看到. 上一页,目录,下一页的网页代码都在<div>下的<a>元素的href里面.不同的是第一章只有2个<a>元素,从二章开始就有3个<a>元素.因此我们可以通过<div>

一个简单的爬取b站up下所有视频的所有评论信息的爬虫

心血来潮搞了一个简单的爬虫,主要是想知道某个人的b站账号,但是你知道,b站在搜索一个用户时,如果这个用户没有投过稿,是搜不到的,,,这时就只能想方法搞到对方的mid,,就是 space.bilibili.com/9444976 后面的那一串数字.偶然看到这个人关注了某个主播,,想到可能这个人会回复主播的视频,于是想着爬到所有up下的视频的评论对应的用户,这样我就可以在数据库里检索昵称得到mid,,,嘿嘿嘿(然而失败了,,不是所有人都像我这么无聊,,,,有些人真的看视频不会回复,, 项目地址: h

Scrapy精华教程(六)——自动爬取网页之II(CrawlSpider)

一.目的. 在教程(二)(http://blog.csdn.net/u012150179/article/details/32911511)中使用基于Spider实现了自己的w3cschool_spider,并在items.py中定义了数据结构, 在pipelines.py中实现获得数据的过滤以及保存. 但是以上述方法只能爬取start_url列表中的网页,而网络爬虫如google等搜索引擎爬虫实现的就是对整个互联网的爬取,所以在本教程中研究使用scrapy自动实现多网页爬取功能. 在教程(五)

【转】 Scrapy研究探索(六)——自动爬取网页之II(CrawlSpider)

转自http://blog.csdn.net/u012150179/article/details/34913315 一.目的. 在教程(二)(http://blog.csdn.net/u012150179/article/details/32911511)中使用基于Spider实现了自己的w3cschool_spider,并在items.py中定义了数据结构, 在pipelines.py中实现获得数据的过滤以及保存. 但是以上述方法只能爬取start_url列表中的网页,而网络爬虫如googl

爬虫概念与编程学习之如何爬取视频网站页面(用HttpClient)(二)

先看,前一期博客,理清好思路. 爬虫概念与编程学习之如何爬取网页源代码(一) 不多说,直接上代码. 编写代码 运行 <!DOCTYPE html><html><head><meta http-equiv="X-UA-Compatible" content="IE=Edge" /><meta http-equiv="Content-Type" content="text/html; c

爬虫小程序 - 王者荣耀全皮肤爬取

爬虫小程序 - 王者荣耀全皮肤爬取 代码如下所示(可直接复制使用): import requests import re import os ''' ps: 出现 <Response [405]> 多运行几次就好了 ''' def Downloed_ksin(ename, **kwargs): # 英雄详情页 url = 'https://pvp.qq.com/web201605/herodetail/' + ename + '.shtml' html = session.get(url=ur