【问题标题】:scrapy response selector to lxml对lxml的scrapy响应选择器
【发布时间】:2016-05-30 15:45:43
【问题描述】:

确实,我详细阅读了这个问题converting scrapy to lxml。 但是在我的项目中,有几十个爬虫使用了scrapy selector。将scrapy逐行转换为lxml会花费我们很多时间。所以我尝试写一些兼容的代码来迁移爬虫。

    class ElemList(list):
        def __init__(self, elem_list=[]):
            super(ElemList, self).__init__(elem_list)
    
        def xpath(self, xpath_str=""):
            res = []
            for elem in self:
                try:
                    e = elem.xpath(xpath_str)
                except Exception as e:
                    continue
                if isinstance(e, str) or isinstance(e, unicode):
                    res.append(e)
                else:
                    res.extend(e)
            return ElemList(res)
    
        def extract(self):
            res = []
            for elem in self:
                if isinstance(elem, str):
                    res.append(elem)
            return res

在响应类中,添加一些初始化调用。

    from lxml import etree
    
    class Response(object):
        def __init__(self):
            self.elem_list = ElemList(etree.HTML(self.html))
        def xpath(self, xpath):
            return self.elem_list.xpath(xpath)

有了这个类,我可以像这样调用响应对象:

    resp.xpath('//h2[@class="user-card-name"]/text()').extract()
    resp.xpath('//h2[@class="user-card-name"]').xpath('*[@class="top-badge"]/a/@href').extract()

它有效。但是新的问题来了,怎么迁移response.css呢?

    baseInfo_div = response.css(".vcard")[0]
    baseInfo_div.css(".vcard-fullname")
    baseInfo_div.css(".vcard-username")
    baseInfo_div.css('li[itemprop="worksFor"]')
    baseInfo_div.css('li[itemprop="homeLocation"]')

【问题讨论】:

  • 有点跑题了,但你为什么要 lxml 而不是 scrapy 选择器?
  • 我们决定不对爬虫使用scrapy,需要迁移我们的爬虫。
  • 你可以使用parsel,它是scrapy 的选择器,没有scrapy 本身。所以你只需要更改导入。

标签: scrapy lxml


【解决方案1】:

您可以尝试使用lxml.cssselect 中的cssselect() 方法来实现您的逻辑,这使您可以使用CSS 选择器表达式从lxmlElement 对象中查询。或者您可以使用 GenericTranslator.css_to_xpath() 将 CSS 选择器转换为 XPath 选择器:

from lxml import html
h = html.fromstring('''<div id="outer">
<div id="inner" class="content body">
       text
</div></div>''')
content = h.cssselect('div.content')[0]
content.text    
# output :
# '\n       text\n'

from cssselect import GenericTranslator
GenericTranslator().css_to_xpath('div.content')    
# output :
# u"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' content ')]"

【讨论】:

    猜你喜欢
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 2020-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多