• Spider-scrapy 中的 xpath 语法与调试


    把setting中的机器人过滤设为False

    ROBOTSTXT_OBEY = False
    

    1 语法

    artcile

    选取所有子节点

    /article

    选取根元素 artile

    article/a

    选取所有属于artile的子元素中的a元素

    //div

    选取所有 div 元素(不管出现在文档任何位置)

    article//div

    选取所有属于artile元素的后代的 div 元素,不管出现在 article 之下的任何位置

    //@class

    选取所有名为 class 的属性。

    /article/div[1]

    选取属于article子元素的第一个div元素

    /article/div[last()]

    选取属于article子元素的最后一个div元素

    /article/div[last()-1]

    选取属于article子元素的倒数第二个div元素

    //div[@lang]

    选取所有拥有lang属性的div元素

    //div[@lang='eng']

    选取所有lang属性为eng的div元素

    debug

    1 pycharm

    id是全局唯一的

    re_selector2 = response.xpath('//*[@id="post-110595"]/div[1]/h1/text()')

    如果class='entry-header'是全局唯一,可以比上面少一层节点。

    re_selector3 = response.xpath("//div[@class='entry-header']/h1/text()")

    2 scrapy shell

    对某一页http://blog.jobbole.com/110595/ 进行debug

    scrapy shell http://blog.jobbole.com/110595/

    得到response对象。

    可以用dir(response)看属性和方法。用type(response)看类型。

    >>> title = response.xpath("//div[@class='entry-header']/h1/text()")
    >>> title
    [<Selector xpath="//div[@class='entry-header']/h1/text()" data='为什么该和程序员约会?我有 20 个理由'>]

    如何获取title中的数据?使用extract()方法,得到数组,再用序号可以得到具体值。

    >>> title.extract()
    ['为什么该和程序员约会?我有 20 个理由']
    >>> title.extract()[0]
    '为什么该和程序员约会?我有 20 个理由'

    不直接extra()是因为title 可以保持为selector对象。

    获取时间,把里面的文本用text()获取出来。再用strip()默认出去默认字符。

    >>> create_date = response.xpath("//p[@class='entry-meta-hide-on-mobile']/text()").extract()[0]
    >>> create_date
    '
    
                2017/03/18 ·  '
    >>> create_date = create_date.strip()
    >>> create_date
    '2017/03/18 ·'
    >>> a = create_date.replace("·","").strip()
    >>> a
    '2017/03/18'
    >>> b = create_date.strip("·")
    >>> b
    '2017/03/18 '
    >>> b = create_date.strip("·").strip()
    >>> b
    '2017/03/18'

    只取多个class属性中的一个,用xpath的函数 contains。

    比如要选取span,但是class有多项。而只想要其中的vote-post-up,可以用xpath的contains。

    <span data-post-id="110595" class=" btn-bluet-bigger href-style vote-post-up   register-user-only "><i class="fa  fa-thumbs-o-up"></i> <h10 id="110595votetotal">2</h10> 赞</span>
    >>> response.xpath("//span[contains(@class, 'vote-post-up')]")
    [<Selector xpath="//span[contains(@class, 'vote-post-up')]" data='<span data-post-id="110595" class=" btn-'>]

    列表生成式

    过滤评论

    >>> response.xpath("//p[@class='entry-meta-hide-on-mobile']/a/text()").extract()[0:]
    ['其他', ' 7 评论 ', '约会']
    >>> [element for element in tag_list if not element.strip().endswith("评论")]
    ['其他', '约会']
    tag_list = [ element for element in tag_list if not element.strip().endswith("评论") ]
    tags = ",".join(tag_list)

    以什么结尾一定是 .endswith()

    extract_first()

    对数组取第0个、第1个的时候,如果数组为空,则可能抛出异常。

    但是如果用extract_first(),不用做异常处理,结果为空或者None。

    def extract_first(self, default=None):
        for x in self:
            return x.extract()
        else:
            return default

    类似于字典的get方法,提取不到就返回空。

    最终 jobbole.py

    # -*- coding: utf-8 -*-
    import re
    import scrapy
    
    
    class JobboleSpider(scrapy.Spider):
        name = "jobbole"
        allowed_domains = ["blog.jobbole.com"]
        start_urls = ['http://blog.jobbole.com/110595/']
    
        def parse(self, response):
            # re_selector1 = response.xpath("/html/body/div[1]/div[3]/div[1]/div[1]/h1")
            # re_selector2 = response.xpath('//*[@id="post-110595"]/div[1]/h1/text()')
            # re_selector3 = response.xpath("//div[@class='entry-header']/h1/text()")
            title  = response.xpath("//div[@class='entry-header']/h1/text()").extract()[0]
            create_date = response.xpath("//p[@class='entry-meta-hide-on-mobile']/text()").extract()[0].strip().replace("·","").strip()
            praise_nums = response.xpath("//span[contains(@class, 'vote-post-up')]//h10/text()").extract()[0]
            fav_nums = response.xpath("//span[contains(@class, 'bookmark-btn')]/text()").extract()[0]
            match_re = re.match(".*?(d+).*", fav_nums)
            if match_re:
                fav_nums = match_re.group(1)
            comment_nums = response.xpath("//a[@href='#article-comment']/span/text()").extract()[0]
            match_re = re.match(".*?(d+).*", comment_nums)
            if match_re:
                comment_nums = match_re.group(1)
    
            content = response.xpath("//div[@class='entry']").extract()[0]
            tag_list = response.xpath("//p[@class='entry-meta-hide-on-mobile']/a/text()").extract()
            tag_list = [ element for element in tag_list if not element.strip().endswith("评论") ]
            tags = ",".join(tag_list)
    
    
            # 通过css选择器提取字段
            title = response.css(".entry-header h1::text").extract()[0]
            create_date = response.css(".entry-meta-hide-on-mobile::text").extract()[0].strip().replace("·","").strip()
            praise_nums = response.css("div.post-adds h10::text").extract()[0]
    
            # fav_nums = response.css("span[class*='bookmark-btn']::text").extract()[0]
            fav_nums = response.css(".bookmark-btn::text").extract()[0]
            match_re = re.match(".*?(d+).*", fav_nums)
            if match_re:
                fav_nums = match_re.group(1)
    
            # comment_nums = response.css("span[class='btn-bluet-bigger href-style hide-on-480']::text").extract()[0]
            comment_nums = response.css("a[href='#article-comment'] span::text").extract_first()
            match_re = re.match(".*?(d+).*", comment_nums)
            if match_re:
                comment_nums = match_re.group(1)
            content = response.css(".entry").extract()[0]
            tag_list = response.css("p.entry-meta-hide-on-mobile a::text").extract()
            tag_list = [element for element in tag_list if not element.strip().endswith("评论")]
            tags = ",".join(tag_list)
            pass
  • 相关阅读:
    UVA 11021繁衍模型+概率计算
    LA 5059博弈+SG函数
    LA 3942 字典树
    Beat---hdu2614
    Wooden Sticks---hdu1051(最长上升子序列)
    欧拉函数基础
    1370
    钱币兑换问题---hdu1284(完全背包)
    Drainage Ditches--hdu1532(网络流 模板)
    Fibonacci--poj3070(矩阵快速幂)
  • 原文地址:https://www.cnblogs.com/Python-XiaCaiP/p/10284253.html
Copyright © 2020-2023  润新知