使用CrawlSpider爬虫爬取猎云网

parse()方法的工作机制

感谢脑补连接

  • 因为使用的yield,而不是return。parse函数将会被当做一个生成器使用。scrapy会逐一获取parse方法中生成的结果,并判断该结果是一个什么样的类型;

  • 如果是request则加入爬取队列,如果是item类型则使用pipeline处理,其他类型则返回错误信息;

  • scrapy取到第一部分的request不会立马就去发送这个request,只是把这个request放到队列里,然后接着从生成器里获取;

  • parse()方法作为回调函数(callback)赋值给了Request,指定parse()方法来处理这些请求 scrapy.Request(url, callback=self.parse);

  • Request对象经过调度,执行生成 scrapy.http.response()的响应对象,并送回给parse()方法,直到调度器中没有Request(递归的思路);

  • 取尽之后,parse()工作结束,引擎再根据队列和pipelines中的内容去执行相应的操作;

  • 程序在取得各个页面的items前,会先处理完之前所有的request队列里的请求,然后再提取items;

  • 这一切的一切,Scrapy引擎和调度器将负责到底。

CrawlSpider 爬虫

之前使用普通的spider ,我们是自己再解析完整个页面后获取下一页的url, 然后从新发送一个请求。有时候我们想要这么

做,只要满足某个条件的url ,都给我进行爬取。那么这个时候我们就可以通过 CrawlSpider 帮助实现。 它继承自Spider ,只

不过实在之前的基础上增加了新的功能,可以定义爬取url 的规则,以后 scrapy 再碰到任何满足条件的url 都会进行爬取,

而不用手动 yield Request.

  1. 创建

scrapy genspider -t crawl name domain

  1. LinkExtractors 链接提取器:
    使用 linkextractors 可以不用程序猿自己提取想要的url, 然后发送请求。这些工作都可以交给这个链接提取器。他会在所有爬的页面中找到满足规则的url ,实现自动爬取。

classscrapy.linkextractors.lxmlhtml.LxmlLinkExtractor(allow=(), deny=(), allow_domains=(), deny_domains=(), deny_extensions=None, restrict_xpaths=(), restrict_css=(), tags=(‘a’, ‘area’), attrs=(‘href’, ), canonicalize=False, unique=True, process_value=None, strip=True)

主要参数解释:更多的去看官方的帮助文档吧

  • allow 一个正则表达式,所有满足这个正则表达式的url 都会被提取。如果是空,则匹配所有链接。
  • deny 一个正则,满足条件的url 会被排除,优先级高于 allow ,如果是空,不会排除任何url.
  • allow_domains 一个字符串或列表,提取这里面指定的域名里的url
  • deny_domains 里面的url 都不会提取
  • restrict_xpath :xpath 的语法或语法的列表,只会提取它扫描出来的链接,过滤作用。
  1. Rule规则类

classscrapy.spiders.Rule(link_extractor=None, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None, errback=None)

  • link_extractor :一个Link Extractor 对象,用来爬取定义后的链接,每一个链接将生成一个request 对象,保存再 link_text 的key 下。如果没有定义,将提取所有链接。
  • callback : 满足这个条件的url,应该要执行那个回调函数。因为 crawspider 使用了parse作为回调函数,因此不要覆盖parse 作为回调函数,否则这个爬虫就不会运行
  • follow:指定根据该规则从response 中提取的链接是否需要跟进
  • process_links: 从link_extractor 中获取到的链接后会传递给这个函数,用来过滤不需要爬取的链接。

案例:猎云网

需求:实现猎云网网站的文件数据爬虫,需要保存标题,发布时间,内容,原创url字段,然后异步保存到mysql 数据库中。

  • 由于我们再解析网页的时候会尝试很多次,但是使用scrapy 框架会自动搞很对网站,所以我们可以再shell 里把相关的语法写好。

shell
这是一个命令行交互模式
通过scrapy shell url地址进入交互模式
这里我么可以通过css选择器以及xpath选择器获取我们想要的内容
在这里插入图片描述
然后再下面写就行啦。。。

当然如果我们使用普通的方法效率是很低的,所以来试试异步。。。
异步:不等任务执行完,直接执行下一个任务。
同步:一定要等任务执行完了,得到结果,才执行下一个任务。

  1. 使用twisted.enterprise.adbapi来创建连接池
  2. 使用runlnteraction来运行插入sql 语句的函数
  3. 再插入sql 语句的函数中,第一个非self的参数就是cursor 对象,使用这个对象执行sql 语句。
开始:
  1. 创建项目:
scrapy startproject leiyun
cd leiyun
scrapy genspider -t crawl lieyun_spider lieyunwang.com

2.修改settings:
除了不遵守机器人协议,请求头,打开管道之外还要配置我们的MySQL数据库

MYSQL_CONFIG={                        # 配置数据库
    'DRIVER':'pymysql', # 驱动
    'HOST':'localhost',
    'PORT': 3306,
    'USER': 'root',
    'PASSWORD': '54567789',
    'DATABASE':'猎云网'             # 操作的数据库
}

在这里插入图片描述
再navicat建好表格
3. 确认需要提取的数据: item

import scrapy

class LieyunItem(scrapy.Item):
    title = scrapy.Field()
    content = scrapy.Field()
    author = scrapy.Field()
    pub_time = scrapy.Field()
    origin = scrapy.Field()
  1. spider
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from ..items import LieyunItem

class LieyunSpiderSpider(CrawlSpider):
    name = 'lieyun_spider'
    allowed_domains = ['lieyunwang.com']
    start_urls = ['https://www.lieyunwang.com/latest/p1.html']

    rules = (
        Rule(LinkExtractor(allow=r'/latest/p\d+.html'), follow=True), # 框架会根据允许的域名自动补上
        # 提取页数的url,选择跟进否则就不会爬取多页,不需要回调函数,因为我们不在这些url里爬取数据
        Rule(LinkExtractor(allow=r'/archives/\d+'),callback='parse_item',follow=False),
        # 根据前一个规则提取到的页面url提取文章的链接,使用回调函数去解析数据然后爬取,不用跟进否则会吧那些推荐的文章也爬出来

    )

    def parse_item(self, response):      # 以下的命令可以再 scrapy shell 中测试的
        title = response.xpath(r'//h1[@class="lyw-article-title"]/text()').getall()
        title = ''.join(title).strip()
        pub_time = response.xpath(r'//h1[@class="lyw-article-title"]/span/text()').getall()
        author = response.xpath(r'//div[@class="author-info"]/a/text()').get()
        origin = response.url
        content = response.xpath(r'//div[@class="main-text"]').get()    # 不用text()了,省的再整格式了

        item = LieyunItem(title=title,pub_time=pub_time,author=author,content=content,origin=origin)
        return item    # 也可以是return item,因为这个页面只有一个item,当有多个是还是用yield
  1. pipelines

@classmethod 修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。

from twisted.enterprise import adbapi # 异步的API ,

class LieyunPipeline(object):
    def __init__(self,mysql_config):
        self.dbpool = adbapi.ConnectionPool(mysql_config['DRIVER'],       # 连接对象
                              host = mysql_config['HOST'],
                              port = mysql_config['PORT'],
                              user = mysql_config['USER'],
                              password = mysql_config['PASSWORD'],
                              db = mysql_config['DATABASE'],
                              charset = 'utf8')

    @classmethod
    def from_crawler(cls,crawler):    # 获取setting 里的数据库配置信息
        mysql_config = crawler.settings['MYSQL_CONFIG']
        return cls(mysql_config) # 这个cls代表了这个类本身,再创建对象的时候,就会调用这个参数。
    # 只要重写了这个方法,再以后创建对象的时候,会调用这个方法来获取pipeline 对象。


    def process_item(self, item, spider):
        result = self.dbpool.runInteraction(self.insert_item,item)           # 运行,再调用insert_item时,会传入cursor 对象
        result.addErrback(self.insert_error)       # 容错处理
        return item

    def insert_item(self,cursor,item):
        sql = 'insert into 猎云网数据(id,title,author,content,pub_time,origin) values(null,%s,%s,%s,%s,%s)'
        args = (item['title'],item['author'],item['content'],item['pub_time'],item['origin'])
        cursor.execute(sql,args)

    def insert_error(self,failure):
        print('出错了。。。。')
        print(failure)

    def close_spider(self,spider):
        self.dbpool.close()
  1. run
from scrapy import cmdline

cmdline.execute("scrapy crawl lieyun_spider".split(" "))

。。。呀。。。为了找那个打错的字母捣鼓了好久,,,,,当我发现把from_crawler 写成了 from_crawier时,,,,@#$%@%#%#%#

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值