如果所述元素中包含其他元素,如何在scrapy中选择元素内的所有文本?

时间:2017-05-19 13:20:16

标签: python scrapy web-crawler

我有一个包含这样的部分的页面。它基本上是主要p标签中的一个问题,但每次有某些上标时,都会破坏我的代码。

我想得到的文字是 - “对于任何三角形ABC的余弦规则,b2等于”

<p><span class="mcq_srt">MCQ.</span>For Cosine Rule of any triangle ABC, b<sup>2</sup> is equal to</p>
    <ol>
        <li>a<sup>2</sup> - c<sup>2</sup> + 2ab cos A</li>
        <li>a<sup>3</sup> + c<sup>3</sup> - 3ab cos A</li>
        <li>a<sup>2</sup> + c<sup>2</sup> - 2ac cos B</li>
        <li>a<sup>2</sup> - c<sup>2</sup> 4bc cos A</li>
    </ol>

当我尝试选择p时,我错过了应该是超级脚本的2。此外,我还在列表中得到两个句子,当我尝试存储答案时,它会弄乱一些事情

 response.css('p::text') > ["For Cosine Rule of any triangle ABC, b", "is equal to"]

我可以尝试使用

进行选择
response.css('p sup::text')

然后尝试合并它,检查一个句子是否以一个小写字母开头但当我有很多问题时搞砸了。这是我在解析方法中所做的事情

`
    questions = [x for x in questions if x not in [' ']] #The list I get usually has a bunch of ' ' in them
    question_sup = response.css('p sup::text').extract()
    answer_sup = response.css('li sup::text').extract()
    all_choices = response.css('li::text')[:-2].extract() #for choice
    all_answer = response.css('.dsplyans::text').extract() #for answer

    if len(question_sup) is not 0:
        count=-1
        for question in questions:
            if question[1].isupper() is False or question[0] in [',', '.']: #[1] because there is a space at the starting
                questions[count]+=question_sup.pop(0)+question
                del questions[count+1]

            count+=1

我上面尝试的失败了很多次,我不知道如何调试它。我正在抓取很多页面,我不知道如何调试它。我一直得到一个无法弹出空列表错误。我想,那是因为我正在尝试的东西出了问题。任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:3)

如果您选择p中包含p文本的所有元素,包括''本身,您将获得一个尊重订单的文本节点列表,因此您只需将列表加入{ {1}}。这里:

>>> from scrapy.selector import Selector
>>> p = Selector(text='<p>For Cosine Rule of any triangle ABC, b<sup>2</sup> is equal to</p>')
>>> t = p.css('p::text, p *::text')  # Give me the text in <p>, plus the text of all of its descendants
>>> ''.join(t.extract())
'For Cosine Rule of any triangle ABC, b2 is equal to'

当然,你会松开超级脚本表示法。如果你需要保留它,你可以这样做:

>>> from scrapy.selector import Selector
>>> p = Selector(text='<p>For Cosine Rule of any triangle ABC, b<sup>2</sup> is equal to</p>')
>>> t = p.css('p::text, p *')
>>> result = []
>>> for e in t:
...     if type(e.root) is str:
...         result.append(e.root)
...     elif e.root.tag == 'sup':
...         result.append('^' + e.root.text)  # Assuming there can't be more nested elements
...     # handle other tags like sub
...
>>> ''.join(result)
'For Cosine Rule of any triangle ABC, b^2 is equal to'