热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

(3)分布式下的爬虫Scrapy应该如何做-递归爬取方式,数据输出方式以及数据库链接

放假这段时间好好的思考了一下关于Scrapy的一些常用操作,主要解决了三个问题:1.如何连续爬取2.数据输出方式3.数据库链接一,如何连续爬取:思

  放假这段时间好好的思考了一下关于Scrapy的一些常用操作,主要解决了三个问题:

  1.如何连续爬取

  2.数据输出方式

  3.数据库链接

 

一,如何连续爬取:

 

   思考:要达到连续爬取,逻辑上无非从以下的方向着手

   1)预加载需要爬取的列表,直接到这个列表都处理完,相应的爬取工作都已经完成了。

   2)从第一页开始爬取,遇到有下一页标签的,那继续爬取,如果没有下一页类似的标签,那表示已经爬到最后一页

   3)分析当前页面的所有链接,对于链接符合某种特定规则的,继续爬取,如果没有那表示爬取工作完成(此时需要建立已经爬取列表,防止重复操作)

 

   一般会于定向的爬虫,比如爬取某宝或者某东的数据时,可以采用方式一,二,写好规则就可以了,也方便维护。

   1.1对于预加载的列表,那根据需要生成列表就可以了。

   在start_urls 里面生成相应的列表就可以,这里引入一个概念,列表推导式。

   我们将代码变换成如下:

   

from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector
from cnblogs.items import CnblogsItem

class CnblogsSpider(BaseSpider):
    name = "cnblogs"
    allowed_domains = ["cnblogs.com"]
    start_urls = [
        'http://www.cnblogs.com/#p%s' % p for p in xrange(1, 11)
        ]

    def parse(self, response):
        self.log("Fetch douban homepage page: %s" % response.url)
        hxs = HtmlXPathSelector(response)

        # authors = hxs.select('//a[@class="titlelnk"]')

        items = hxs.select('//a[contains(@class, "titlelnk")]')

        listitems = []

        for author in items:
            # print author.select('text()').extract()
            item = CnblogsItem()
            # property
            item['Title'] = ''.join(author.select('text()').extract())
            item['TitleUrl'] = author.select('@href').extract()
            listitems.append(item)

        return listitems


在这里,start_urls里面使用列表推导式,爬出了一共10页的数据。

1.2对于爬取下一页实现全趴取的过程,就需要使用yield关键字


我们就虫师的博客来进行测试实验:

http://www.cnblogs.com/fnng/default.aspx?page=1

 

这里介绍一个scrapy 一个非常有用的技巧,scrapy shell ,因为使用 xpath 可以帮助我们调试xpath语法(或者使用firebug又或者是chrome都可以)

语法:scrapy shell http://你要调试xpath的网址

 

这里我就不继续讲xpath的语法了,自己去搜一下,相比正则要相对简单好理解。

 

相应的Spider可以这样编写:

 

# -*- coding: utf-8 -*-
from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector
from cnblogs.items import CnblogsItem
from scrapy.http import Request
from scrapy import log
# please pay attention to the encoding of info,otherwise raise error of decode 
import sys
reload(sys)
sys.setdefaultencoding('utf8')

class BlogsSpider(BaseSpider):
    name = "cnblogs_blogs"
    allowed_domains = ["cnblogs.com"]
    start_urls = [
        'http://www.cnblogs.com/fnng/default.aspx?page=1'
        ]

    def parse(self, response):
        hxs = HtmlXPathSelector(response)
        # authors = hxs.select('//a[@class="titlelnk"]')
        # sel.xpath('//a[@class="PostTitle"]').xpath('text()')
        items = hxs.select('//a[@class="PostTitle"]')
        a_page = hxs.select('//div[@id="pager"]/a')
        for a_item in items:
            item = CnblogsItem()
            # property
            item['Title'] = ''.join(a_item.xpath('text()').extract())
            item['TitleUrl'] = a_item.xpath('@href').extract()
            yield item

        # get the page index
        log.msg(len(a_page))
        if len(a_page) > 0:
            for a_item in a_page:
                page_text = ''.join(a_item.xpath('text()').extract())
                if page_text == '下一页'.encode('utf-8') or 'Next' in page_text:
                    next_url = ''.join(a_item.xpath('@href').extract())
                    log.msg(next_url)
                    yield Request(next_url, callback=self.parse)
                    break

 

我们来运行看看效果如何:

 

所有的数据完整,效果还是不错的。

关于第三种,以规则来规划爬虫的机制,在以后会介绍 :)

 

二,数据输出的方式:

 

   上面的scrapy命令是:scrapy crawl cnblogs_blogs --nolog -o cnblogs_blogs.json -t json

   那结果输出的就是json格式的文件,-t 指的是输出文件格式,json ,-t 支持下列参数:    

   xml
   csv
   json
   jsonlines
   jl
   pickle
   marshal

   一般选择xml ,csv,json三种格式就够了,这样可以很方便的导入各种数据库。

   更多的参考:http://doc.scrapy.org/en/latest/topics/feed-exports.html 

三,数据库连接:

 

   数据保存为文件的形式然后导入是一个不错的选择,不过一般都会有一定的IO开销,一般可以将Item直接保存到数据库中,这个时候就要引入pipelines这个部件了。

   在我们项目的根目录下有一个名为:pipelines.py文件,我们在设置里面首先启用这个文件,在启用之后,spider得到的item都会传入到这个部件中进行二次处理,

   3.1在settings.py中启用pipelines

   

ITEM_PIPELINES = {
    'cnblogs.pipelines.CnblogsPipelineobj': 300,
}

   注意命名方式:botname.moudlename.classname 要不然会找不到指定的模块。

   3.2 编写pipelines

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


import MySQLdb
import MySQLdb.cursors
import logging
from twisted.enterprise import adbapi

class CnblogsPipelineobj(object):
    def __init__(self):
        self.dbpool = adbapi.ConnectionPool(
                dbapiName ='MySQLdb',
                host ='127.0.0.1',
                db = 'cnblogs',
                user = 'root',
                passwd = '密码',
                cursorclass = MySQLdb.cursors.DictCursor,
                charset = 'utf8',
                use_unicode = False
        )

    # pipeline dafault function
    def process_item(self, item, spider):
        query = self.dbpool.runInteraction(self._conditional_insert, item)
        logging.debug(query)
        return item


    # insert the data to databases
    def _conditional_insert(self, tx, item):
        parms = (item['Title'], item['TitleUrl'])
        sql = "insert into blogs values('%s','%s') " % parms
        #logging.debug(sql)
        tx.execute(sql)

  

OK.运行一下看一下效果如何

 

 

 

中文数据得以保存,OK

 

总结:本次主要多三个方向来解决连续爬取文章内容,并将获得内容保存的问题,不过文中主要介绍的,还是以定向为基础的爬取,和以规则来构建的爬虫还是有区别,下篇文章将介绍。

 


推荐阅读
  • 第七课主要内容:多进程多线程FIFO,LIFO,优先队列线程局部变量进程与线程的选择线程池异步IO概念及twisted案例股票数据抓取 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • Android实战——jsoup实现网络爬虫,糗事百科项目的起步
    本文介绍了Android实战中使用jsoup实现网络爬虫的方法,以糗事百科项目为例。对于初学者来说,数据源的缺乏是做项目的最大烦恼之一。本文讲述了如何使用网络爬虫获取数据,并以糗事百科作为练手项目。同时,提到了使用jsoup需要结合前端基础知识,以及如果学过JS的话可以更轻松地使用该框架。 ... [详细]
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • 本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ... [详细]
  • 使用Spring AOP实现切面编程的步骤和注意事项
    本文介绍了使用Spring AOP实现切面编程的步骤和注意事项。首先解释了@EnableAspectJAutoProxy、@Aspect、@Pointcut等注解的作用,并介绍了实现AOP功能的方法。然后详细介绍了创建切面、编写测试代码的过程,并展示了测试结果。接着讲解了关于环绕通知的使用方法,并修改了FirstTangent类以添加环绕通知方法。最后介绍了利用AOP拦截注解的方法,只需修改全局切入点即可实现。使用Spring AOP进行切面编程可以方便地实现对代码的增强和拦截。 ... [详细]
  • 本文总结了初学者在使用dubbo设计架构过程中遇到的问题,并提供了相应的解决方法。问题包括传输字节流限制、分布式事务、序列化、多点部署、zk端口冲突、服务失败请求3次机制以及启动时检查。通过解决这些问题,初学者能够更好地理解和应用dubbo设计架构。 ... [详细]
  • Python教学练习二Python1-12练习二一、判断季节用户输入月份,判断这个月是哪个季节?3,4,5月----春 ... [详细]
  • 很多时候在注册一些比较重要的帐号,或者使用一些比较重要的接口的时候,需要使用到随机字符串,为了方便,我们设计这个脚本需要注意 ... [详细]
  • Opencv提供了几种分类器,例程里通过字符识别来进行说明的1、支持向量机(SVM):给定训练样本,支持向量机建立一个超平面作为决策平面,使得正例和反例之间的隔离边缘被最大化。函数原型:训练原型cv ... [详细]
  • 1关于字符串相邻的两个或多个字符串字面值(引号引起来的字符)将会自动连接到一起:str_catpython!str_cat输出:python!把很长 ... [详细]
author-avatar
阳吉登
这个家伙很懒,什么也没留下!
Tags | 热门标签
RankList | 热门文章
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有