zoukankan      html  css  js  c++  java
  • scrapy基础 之 静态网页实例

    1,scrapy爬虫基本流程:

        1. 创建一个新的Scrapy Project

        > scrapy startproject 项目名称    #系统会在当前目录下创建一个项目名称命名的文件夹,其下包含以下文件:

            scrapy.cfg: 项目配置文件

            items.py: 需要提取的数据结构定义文件,在items.py里面定义我们要抓取的数据:

            pipelines.py:管道定义,PipeLine用来对Spider返回的Item列表进行保存操作,可以写入到文件、或者数据库等。

            settings.py: 爬虫配置文件,包括发送请求次数,间隔时间,等等

            spiders: 放置spider的目录,也就是爬虫的主程序,至少包含以下三个要素:name:spider的标识,parse()方法:当start_urls里面的网页抓取下来之后需要调用这个方法解析网页内容,同时需要返回下一个需要抓取的网页,或者返回items列表。start_url :一个url列表,spider从这些网页开始抓取.

        2. 定义你需要从网页中提取的元素Item

        3.实现一个Spider类,通过接口完成爬取URL和提取Item的功能

        4. 实现一个Item PipeLine类,完成Item的存储功能

    注意:

        > scrapy startproject huxiu2    #在当前文件夹创建一个名为huxiu2的文件夹,文件夹有settings,items,pipeline等文件构成一个爬虫框架

        自己写的爬虫程序要写在projectname/projectname/spiders目录下

    2,配置items文件

    目标:虎嗅网新闻列表的名称、链接地址和摘要爬取下来。

    import scrapy
    class HuxiuItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        title=scrapy.Field()
        link=scrapy.Field()
        desc=scrapy.Field()
        posttime=scrapy.Field()

    注意:title,auther等内容将会是每行中存放信息的条目,也就是需要爬取的信息。

               输出和爬取程序不在一个文件里的好处是,未来可以使用Scrapy中其他有用的组件和帮助类。虽然目前感受不深,先按照框架来吧

    3,写第一个spider

    必不可少的要素:如果采用了items.py一定要先import一下,继承scrapy.Spider类并且有name,start_urls,parse。

    from huxiu2.items import Huxiu2Item    #整个爬虫project的名字为huxiu2,
    import scrapy
    
    class Huxiu2Spider(scrapy.Spider):
        name = "huxi2"
        allowed_domains = ['huxiu.com']  # 只有这个域名下的子域名可以被允许爬取
        start_urls = ['http://www.huxiu.com/index.php']
    
        def parse(self, response):
            for sel in response.xpath('//div[@class ="mod-info-flow"]/div/div[@class="mob-ctt index-article-list-yh"]'):
                item = HuxiuItem()
                item['title'] = sel.xapth('h2/a/text()').extract_first()
                item['link'] = sel.xpath('h2/a/@href').extract_first()
                url = response.urljoin(item['link'])
                item['desc'] = sel.path('div[@class ="mob-sub"]/text()').extract_first()
                print item['title'],item['link'], item['desc']
    #结果是无法爬取,估计需要设置headers。下文是修正版,啦啦啦,好from huxiu2.items import Huxiu2Item #整个爬虫project的名字为huxiimpofrom huxiu2.items import Huxiu2Item
    import scrapy
    
    class Huxiu2Spider(scrapy.Spider):
        name = "huxiu"
        # allowed_domains = ['huxiu.com']  # 只有这个域名下的子域名可以被允许爬取
        # start_urls = ['http://www.huxiu.com']    #有了重定义的start_requests就不用start_urls啦
        def start_requests(self):    
    # start_urls作用是开始请求第一个网址,默认就是使用start_requests方法,不带任何参数地请求,现在我们为了爬取信息必须要带上参数,
    # 所以我们要自定义一下这个方法。
    # 下方的request默认参数是: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。 所以cookie和headers是分开的,至于其余的参数,以后详解
    url='http://www.huxiu.com/index.php' head={ "User-Agent":"info" } cookie={'key':'value'} #自己去网页f12看哦,复制以后改成字典格式 yield scrapy.Request(url=url,cookies=cookie,callback=self.parse,headers=head) pass def parse(self, response): print ">>>>>呵呵" for i in response.xpath('//div[@class="mod-b mod-art clearfix "]'): item=Huxiu2Item() item['title'] = i.xpath('./div[@class="mob-ctt index-article-list-yh"]/h2/a/text()').extract_first() item['link']=i.xpath('./div[@class="mob-ctt index-article-list-yh"]/h2/a/@href').extract_first() item['desc']=i.xpath('.//div[@class="mob-sub"]/text()').extract_first() print item['title'],item['link'],item['desc']

     4,处理链接进入到每篇文章中获取信息

        在items.py文件中,我们定义了posttime=scrapy.Field(),但是发送时间只有在具体的文章被打开以后才能够得到,所以,我们要同时处理第二层网址。

    from huxiu2.items import Huxiu2Item    #整个爬虫project的名字为huxiu2,
    import scrapy
    
    class Huxiu2Spider(scrapy.Spider):
        name = "huxi3"
        allowed_domains = ['huxiu.com']  # 只有这个域名下的子域名可以被允许爬取
        start_urls = ['http://www.huxiu.com']    #相当于第一次发出请求
    
        def parse(self, response):
            for sel in response.xpath('//div[@class ="mod-info-flow"]/div/div[@class="mob-ctt index-article-list-yh"]'):
                item = HuxiuItem()    #实例化一个item用于储存数据
                item['title'] = sel.xapth('h2/a/text()').extract_first()
                item['link'] = sel.xpath('h2/a/@href').extract_first()
                url = response.urljoin(item['link'])    #生成可访问的打开每一篇文章的新网址
                item['desc'] = sel.xpath('div[@class ="mob-sub"]/text()').extract_first()
                print item['title'],item['link'], item['desc']
                yield scrapy.Request(url,callback=self.parse_artical)    #开始第二层的请求,网址是url,callbac参数定义的是第二层爬取将调动哪个函数
    
        def parse_artical(self,response):
            item=Huxiu2Item()    #同样需要实例一下用来储存数据
            item['posttime']=response.xpath('//span[@class="article-time pull-left"]/text()').extract_first()
            item['link']=response.url    #进去第二层以后顺带更新一下litem['link'],因为之前的link不完整,不用之前的url变量是因为在此处更新可以确保新网址可打开。
            print item['posttime'],item['link']
            yield item

     5,导出抓取数据

    第一种方法:直接打印:>scrapy crawl huxi3

    第二种方法:导出结果到jason文件:>scrapy crawl huxiu -o items.json

    第三种方法:保存到数据库

        保存到数据库,可以直接在spiders里面定义,也可以使用piplines

        直接写在spiders里面的方法:

    from huxiu2.items import Huxiu2Item   #整个爬虫project的名字为huxiu2,
    import scrapy,pymysql
    
    
    class Huxiu2Spider(scrapy.Spider):
        name = "huxiu"
        def start_requests(self):
            url='http://www.huxiu.com/index.php'
            head={
                "User-Agent":"xxx"
            }
            cookie={
                "xxx": "yyy"
            }
            yield scrapy.Request(url=url,cookies=cookie,callback=self.parse,headers=head)
            pass
    
        def parse(self, response):
            db = pymysql.connect("localhost", "root", "xxxx", "xxxx")    #先要连接上数据库
            cursor = db.cursor()    
            sql="""create table huxiu(`title` varchar(50),`link` varchar(50),`desc` varchar(50))DEFAULT CHARSET=utf8"""    #设置数据表的编码方式
            try:
                cursor.execute(sql)    #创建数据表新表
                db.commit()
            except:
                db.rollback()
                print "error first try"
    for i in response.xpath('//div[@class="mod-b mod-art clearfix "]'): item=Huxiu2Item() item['title'] = i.xpath('./div[@class="mob-ctt index-article-list-yh"]/h2/a/text()').extract_first().encode("utf-8") tmplink=i.xpath('./div[@class="mob-ctt index-article-list-yh"]/h2/a/@href').extract_first().encode("utf-8") item['link']=response.urljoin(tmplink).encode("utf-8") item['desc']=i.xpath('.//div[@class="mob-sub"]/text()').extract_first().encode("utf-8") #加encode的原因是原数据是unicode格式的 #print '第一层',item['title'],item['link'],item['desc'] a=str(item['title']) b=str(item['link']) c=str(item['desc']) print item['title'],"结果" sql2="""INSERT INTO huxiu VALUES ('%s', '%s','%s')""" % (a,b,c) #传参到sql语句中,%s表示传的是字符串 try: cursor.execute(sql2) db.commit() except: db.rollback() print "error of second try" db.close()

        使用pipeline的方法:

        注意:要想使用pipeline,

              首先得在spiders中有yield item作为结尾,只要这样才能生成item,否则item是空的;

                   其次得在settings中启用pipelines,格式如下:ITEM_PIPELINES = {'huxiu2.pipelines.Huxiu2PipelinesJson': 300,},字典的键是自定义的pipeline函数名

                   最后要注意pipeline内的class下的函数基本有三个,分别在开始中间和结束时候执行

    spider的代码:

    from huxiu2.items import Huxiu2Item   #整个爬虫project的名字为huxiu2,
    import scrapy,pymysql
    
    class Huxiu2Spider(scrapy.Spider):
        name = "huxiu"
        def start_requests(self):    #自定义的request方法
            url='http://www.huxiu.com/index.php'
            head={
                "User-Agent":"yyy"
            }
            cookie={
                "xxx": "yyy"
            }
            yield scrapy.Request(url=url,cookies=cookie,callback=self.parse,headers=head)
            pass
    
        def parse(self, response):    #自定义的信息获取函数
            for i in response.xpath('//div[@class="mod-b mod-art clearfix "]'):
                item=Huxiu2Item()
                item['title'] = i.xpath('./div[@class="mob-ctt index-article-list-yh"]/h2/a/text()').extract_first().encode("utf-8")
                tmplink=i.xpath('./div[@class="mob-ctt index-article-list-yh"]/h2/a/@href').extract_first().encode("utf-8")
                item['link']=response.urljoin(tmplink).encode("utf-8")
                item['desc']=i.xpath('.//div[@class="mob-sub"]/text()').extract_first().encode("utf-8")
                print '第一层',item['title'],item['link'],item['desc']    #为了看到是否可以成功爬取信息,为了搞明白pipelines的原理
                yield item    #yield item非常必要

    pipelines的代码:

    # -*- coding: utf-8 -*-
    
    # Define your item pipelines here
    #
    # Don't forget to add your pipeline to the ITEM_PIPELINES setting
    # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
    
    import json
    
    class Huxiu2PipelinesJson(object):
        def __init__(self):
            print '开始时候执行'    #在得到有用数据以前打印出来
            self.file=open('Huxiu.json','w')    #会在当前目录生成Huxiu.json文件
    
        def process_item(self, item, spider):
            print 'process_item running'    #每次print一组信息以后就会打印出这句话,说明item是一条一条写进json文件中的,而不是生成item以后再总的写进去
            content=json.dumps(dict(item),ensure_ascii=False)+'
    '    #python信息转化为json信息的函数
            self.file.write(content)
            return item
    
        def close_spider(self,spider):
            print '结束时候'    #有用的信息执行完毕后打印出来这句话
            self.file.close()
  • 相关阅读:
    手机验证码登录注册--
    防止注册机,登录时-验证码图片的生成=前端vue+后端node
    VUE中数据排序sort() / 数据反转 reverse() 的使用
    将后台数据数组对象(对象里边包含数组对象)---改为前端想要的数组对象--改变key值(替换)
    vue--ui:antd pro框架--vue.config.js引入高德地图--描绘轨迹
    创建数据库-表-增加,设置主键
    mysql--各种安装包版本安装
    Vuex异步请求存取步骤
    从后往前查找去掉字符串最指定元素
    python安装第三方库
  • 原文地址:https://www.cnblogs.com/0-lingdu/p/9532350.html
Copyright © 2011-2022 走看看