美文网首页
2020-07-19--scrapy框架2

2020-07-19--scrapy框架2

作者: program_white | 来源:发表于2020-07-20 21:43 被阅读0次

    scrapy调试

    通常,运行scrapy爬虫的方式是在命令行输入scrapy crawl ,调试的常用方式是在命令行输入scrapy shell 。总的来说,调试方法比较单一。
    其实,还有两种调试方法,可以在pycharm中实现调试。

    1.使用scrapy.cmdline的execute方法 首先,在项目文件scrapy.cfg的同级建立main.py文件(注意,必须是同级建立),在其中键入如下代码:

    from scrapy.cmdline import execute
    
    execute('scrapy crawl blog'.split())
    # 或
    # execute(['scrapy', 'crawl', 'spider_name'])   spider_name替换为你自己的爬虫名称
    

    Spiders

    Spider类定义了如何爬取某个网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。简而言之,Spider就是你定义爬取的动作及分析某个网页(或者是有些网页)的地方。

    对spider来说,爬取的循环类似如下:

    以初始的URL初始化Request,并设置回调函数。当该request下载完毕并返回时,将生成response,并作为参数传给该回调函数。spider中初始的request是通过调用start_requests() 来获取。start_requests() 读取start_urls中的URL,并以parse为回调函数生成 Request。

    在回调函数内分析返回的(网页)内容,返回 Item 对象、dict、 Request 或者一个包括三者的可迭代容器。 返回的Request对象之后会经过Scrapy处理,下载相应的内容,并调用设置的callback函数(函数可相同)。

    在回调函数内,您可以使用 选择器(Selectors) (您也可以使用BeautifulSoup, lxml 或者您想用的任何解析器) 来分析网页内容,并根据分析的数据生成item。

    最后,由spider返回的item将被存到数据库(由某些 Item Pipeline 处理)

    Scrapy爬取博客园精华区内容

    之前我们都是爬取了一个页面,这次爬取多个页面

    编写items.py文件 定义需要爬取的内容。

    class CnblogsItem(scrapy.Item):
        # define the fields for your item here like:
        post_author = scrapy.Field()    #发布作者
        author_link = scrapy.Field()    #作者博客主页链接
        post_date = scrapy.Field()      #发布时间
        digg_num = scrapy.Field()       #推荐数
        title = scrapy.Field()          #标题
        title_link = scrapy.Field()     #标题链接
        item_summary = scrapy.Field()   #摘要
        comment_num = scrapy.Field()    #评论数
        view_num = scrapy.Field()       #阅读数
    

    在spiders/blog.py中编写爬虫:

        def parse(self, response:HtmlResponse):
            # BlogItem
            # 获取文章对象列表
            blist = response.xpath('//div[@id="post_list"]/div[@class="post_item"]')
            print(blist)
    
            for it in blist:
                blog = CnblogsItem()
    
                #作者
                auth = it.xpath('.//div[@class="post_item_body"]/div[1]/a/text()').extract_first()
                #作者blog主页连接
                auth_url = it.xpath('.//div[@class="post_item_body"]/div[1]/a/@href').extract_first()
                #发布时间
                time = it.xpath('.//div[@class="post_item_body"]/div[1]/text()').extract()
                # 推荐数
                digg_num = it.xpath('./div[1]/div[1]/span/text()').extract_first()
                # 标题
                title = it.xpath('.//div[@class="post_item_body"]//h3/a/text()').extract_first()
                # 标题链接
                title_link = it.xpath('.//div[@class="post_item_body"]//h3/a/@href').extract_first()
                # 摘要
                item_summary = it.xpath('.//div[@class="post_item_body"]/p/text()').extract_first()
                # 评论数
                comment_num = it.xpath('.//div[@class="post_item_body"]/div[1]/span[1]/a/text()').extract_first()
                # 阅读数
                view_num = it.xpath('.//div[@class="post_item_body"]/div[1]/span[2]/a/text()').extract_first()
    
                print(auth,auth_url,time,digg_num,title,title_link,item_summary,comment_num,view_num)
                blog['post_author'] = auth
                blog['author_link'] = auth_url
                blog['post_date'] = time
                blog['digg_num'] = digg_num
                blog['title'] = title
                blog['title_link'] = title_link
                blog['item_summary'] = item_summary
                blog['comment_num'] = comment_num
                blog['view_num'] = view_num
                yield blog
    
            #获取下一页链接
            #a[text()="Next >"]:获取文本内容为Next >的a标签
            next = response.xpath('//a[text()="Next >"]/@href').extract_first()
            # print(next)
            if next:
                next_url = f'http://www.cnblogs.com{next}'
                yield scrapy.Request(
                    next_url,
                    callback=self.parse
                )
    
    

    分析:

    1. 首先获取第一个url,进入parse函数,传进来的response是当前页的响应。
    2. 根据xpath语法获取每个列表项的对象,返回一个列表blist。
    3. 遍历该列表,分别获取每一项的元素对象it,在it的基础上再进行解析,分别获取作者,作者链接,发布时间。推荐数,标题,标题链接,摘要,评论数,阅读数的对象,使用extract()/extract_first()转为单个对象/列表。

    4.创建item数据包,将这些数据加入item数据对象中,yield发送给引擎-->管道文件。
    到此第一页的数据爬取完成。
    5.利用response解析到Next按钮的链接(也就是下一页的url)
    6.判断该url是否存在,如果存在,yield给调度器一个scrapy下的Request()对象,该对象传递两个值,下一个url和回调函数名,进行下一次的爬取。

    当管道文件下有多个类时需要判断类型item与需要获取的类型是否一致。

    CrawlSpider

    class scrapy.spiders.CrawlSpider 在爬取一些特殊类型的网站时,比如一些博客类网站,其网页的链接都会有一些特殊的形式

    http://www.cnblogs.com/book/7357421.html
    http://www.cnblogs.com/book/7356835.html
    

    比如我们想爬取博客链接,会发现,除了最后的几个数字不同,其他的内容是相同的,因此,我们就可以通过这个类来进行自动抓取相似的链接,而无需我们自己定义。

    CrawlSpider类定义了如下的属性和方法:

    • rules 一个包含一个(或多个) Rule 对象的集合(list)。 每个 Rule 对爬取网站的动作定义了特定表现。 Rule对象在下边会介绍。 如果多个rule匹配了相同的链接,则根据他们在本属性中被定义的顺序,第一个会被使用。

    • CrawlSpider需要配合scrapy.spiders.Rule类来实现定义规则 下面介绍scrapy.spiders.Rule类 class scrapy.spiders.Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None)

    • link_extractor 这是一个 Link Extractor 对象。 其定义了如何从爬取到的页面提取链接。

    • callback 这是一个callable或string(该spider中同名的函数将会被调用)。 从link_extractor中每获取到链接时将会调用该函数。该回调函数接受一个response作为其第一个参数, 并返回一个包含 Item 以及(或) Request 对象(或者这两者的子类)的列表(list) cb_kwargs 包含传递给回调函数的参数(keyword argument)的字典。 follow 是一个布尔(boolean)值,指定了根据该规则从response提取的链接是否需要跟进。 如果 callback 为None, follow 默认设置为 True ,否则默认为 False 。 process_links 是一个callable或string(该spider中同名的函数将会被调用)。 从link_extractor中获取到链接列表时将会调用该函数。该方法主要用来过滤。 process_request 是一个callable或string(该spider中同名的函数将会被调用)。 该规则提取到每个request时都会调用该函数。该函数必须返回一个request或者None。 (用来过滤request)

    CrawlSpider爬取读书网

    爬取网页https://www.dushu.com/book/1163_2.html


    上边的2就是页数。

    一、开始一个读书网项目

    scrapy startproject 项目名称
    cd 项目名称/项目名称/spiders
    scrapy genspider -t crawl 爬虫名称 域名

    scrapy startproject dushu      #创建dushu项目
    cd dushu/dushu/spiders       #进入项目下的spiders目录下
    scrapy genspider -t crawl ds www.dushu.com         #创建CrawlSpider爬虫文件
    

    使用pycharm打开项目,项目结构与上一章结构一致,但是文件中内容不同。

    二、链接提取规则

    
    class DsSpider(CrawlSpider):
        name = 'ds'
        allowed_domains = ['www.dushu.com']
        start_urls = ['https://www.dushu.com/book/1163_1.html']
        rules = (
            Rule(LinkExtractor(allow=r'/book/1163_\d+.html'), callback='parse_item', follow=True),
        )
    

    起始url为https://www.dushu.com/book/1163_1.html,当运行爬取时,会自动匹配规则中allow的正则表达式,不断地匹配第二页,第三页的url,并且回调parse_item(),实现多页爬取。

    修改parse_item方法用于解析数据:

        def parse_item(self, response:HtmlResponse):
            # 获取每个书的元素,返回元素对象列表
            blist = response.xpath('//div[@class="bookslist"]/ul/li')
            # print(blist)
            for it in blist:
                book = DushuItem()
                # 从当前it元素位置出发查询下属图片
                img = it.xpath('./div/div/a/img[1]')
                # 获取书名
                title = img.xpath('./@alt').extract_first()
                # 获取书的链接
                src = img.xpath('./@data-original').extract_first()
                # 获取书的作者
                auth = it.xpath('./div/p[1]/text()').extract_first()
                # print(title,src,auth)
                book['title'] = title
                book['src'] = src
                book['auth'] = auth
    
                yield book
    

    四、修改pipelines.py文件用于写入数据

    class DushuPipeline:
        def open_spider(self, spider):
            self.fp = open('dushu.json', 'wb')
            self.exporter = JsonLinesItemExporter(self.fp, ensure_ascii=False, encoding='utf-8')
            self.fp.write(b"[")
        def process_item(self, item, spider):
    
            # self.fp.write(str(item)+"\n")
            self.exporter.export_item(item)
            self.fp.write(b",")
            return item
    
        def close_spider(self, spider):
            self.fp.write(b"]")
            self.fp.close()
    

    items.py

    import scrapy
    
    class DushuItem(scrapy.Item):
    
        # define the fields for your item here like:
        src = scrapy.Field()  # 发布作者
        alt = scrapy.Field()  # 作者博客主页链接
        author = scrapy.Field()  # 发布时间
    

    记得将settings.py中的管道和用户代理和守则修改了。
    运行即可。

    相关文章

      网友评论

          本文标题:2020-07-19--scrapy框架2

          本文链接:https://www.haomeiwen.com/subject/zbydkktx.html