Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在两个元素之间选择和提取文本?_Python_Css_Web Scraping_Css Selectors_Scrapy - Fatal编程技术网

Python 如何在两个元素之间选择和提取文本?

Python 如何在两个元素之间选择和提取文本?,python,css,web-scraping,css-selectors,scrapy,Python,Css,Web Scraping,Css Selectors,Scrapy,我试图刮网站使用刮。页面结构如下所示: <div class="list"> <a id="follows" name="follows"></a> <h4 class="li_group">Follows</h4> <div class="soda odd"><a href="...">Star Trek</a></div> <div class="soda even"

我试图刮网站使用刮。页面结构如下所示:

<div class="list">
  <a id="follows" name="follows"></a>
 <h4 class="li_group">Follows</h4>
 <div class="soda odd"><a href="...">Star Trek</a></div> 
 <div class="soda even"><a href="...</a></div>
 <div class="soda odd"><a href="..">Star Trek: The Motion Picture</a></div>
 <div class="soda even"><a href="..">Star Trek II: The Wrath of Khan</a></div>
 <div class="soda odd"><a href="..">Star Trek III: The Search for Spock</a></div>
 <div class="soda even"><a href="..">Star Trek IV: The Voyage Home</a></div>
  <a id="followed_by" name="followed_by"></a>
 <h4 class="li_group">Followed by</h4>
 <div class="soda odd"><a href="..">Star Trek V: The Final Frontier</a></div>
 <div class="soda even"><a href="..">Star Trek VI: The Undiscovered Country</a></div>
 <div class="soda odd"><a href="..">Star Trek: Deep Space Nine</a></div>
 <div class="soda even"><a href="..">Star Trek: Generations</a></div>
 <div class="soda odd"><a href="..">Star Trek: Voyager</a></div>
 <div class="soda even"><a href="..">First Contact</a></div>
   <a id="spin_off" name="spin_off"></a>
 <h4 class="li_group">Spin-off</h4>
 <div class="soda odd"><a href="..">Star Trek: The Next Generation - The Transinium Challenge</a></div>
 <div class="soda even"><a href="..">A Night with Troi</a></div>
 <div class="soda odd"><a href="..">Star Trek: Deep Space Nine</a></div
</div>
但第一项提取的是所有div,而不仅仅是
后面
后面


任何帮助都会非常有用

您可以尝试使用下面的XPath表达式来获取

  • “以下”块的所有文本节点:

  • “后跟”块的所有文本节点:

  • “衍生”块的所有文本节点:


您可以尝试使用下面的XPath表达式来获取

  • “以下”块的所有文本节点:

  • “后跟”块的所有文本节点:

  • “衍生”块的所有文本节点:


我喜欢在这些情况下使用的提取模式是:

  • 在“边界”上循环(此处,
    h4
    元素)
  • 从1开始枚举时
  • 使用XPath的
    跟随同级
    轴(如@Andersson的回答)在下一个边界之前获取元素
  • 通过计算前面“边界”元素的数量来过滤它们,因为我们通过枚举知道我们在哪里
这就是循环:

$ scrapy shell 'http://www.imdb.com/title/tt0092455/trivia?tab=mc&ref_=tt_trv_cnn'
(...)
>>> for cnt, h4 in enumerate(response.css('div.list > h4.li_group'), start=1):
...     print(cnt, h4.xpath('normalize-space()').get())
... 
1 Follows 
2 Followed by 
3 Edited into 
4 Spun-off from 
5 Spin-off 
6 Referenced in 
7 Featured in 
8 Spoofed in 
这是使用枚举获取边界之间元素的一个示例(注意,这在表达式中使用带
$cnt
的XPath变量,并在
.XPath()中传递
cnt=cnt
):

下面是如何使用它来填充和项目(这里,我使用一个简单的dict只是为了说明):


我喜欢在这些情况下使用的提取模式是:

  • 在“边界”上循环(此处,
    h4
    元素)
  • 从1开始枚举时
  • 使用XPath的
    跟随同级
    轴(如@Andersson的回答)在下一个边界之前获取元素
  • 通过计算前面“边界”元素的数量来过滤它们,因为我们通过枚举知道我们在哪里
这就是循环:

$ scrapy shell 'http://www.imdb.com/title/tt0092455/trivia?tab=mc&ref_=tt_trv_cnn'
(...)
>>> for cnt, h4 in enumerate(response.css('div.list > h4.li_group'), start=1):
...     print(cnt, h4.xpath('normalize-space()').get())
... 
1 Follows 
2 Followed by 
3 Edited into 
4 Spun-off from 
5 Spin-off 
6 Referenced in 
7 Featured in 
8 Spoofed in 
这是使用枚举获取边界之间元素的一个示例(注意,这在表达式中使用带
$cnt
的XPath变量,并在
.XPath()中传递
cnt=cnt
):

下面是如何使用它来填充和项目(这里,我使用一个简单的dict只是为了说明):


如果有帮助的话,imdb.com有一个(un)官方API,如果我记得清楚的话,你可以将所有数据清理干净。如果有帮助的话,imdb.com有一个(un)官方API,如果我记得清楚的话,你可以将所有数据清理干净。你甚至可以将
[./前面的兄弟姐妹::h4[1][.=“后面的”]
简化为
[./前面的兄弟姐妹::h4[1]=“跟随”]
你真是太棒了,安德森爵士。多好的表情啊!!!可以用相同的元素创建css选择器来定位相同的东西吗?一个例子就足够了。谢谢。我不确定是否有办法将提供的XPath表达式转换为相同的CSS选择器。我知道有
符号表示即时的前面和前面的元素,但它们似乎还不支持……为了学习,安德森爵士在这一主题上还需要了解最后一件事。为什么是“h4[1]”,我的意思是为什么不在上面创建的xpath中索引[0]或[2]?对不起,我不知道。
h[1]
表示前面的第一个标题。请注意,与编程语言中的索引以
0
开头不同,在XPath中,索引以
1
开头,您甚至可以将
[/前面的兄弟姐妹::h4[1][.=“followers”]
简化为
[/前面的兄弟姐妹::h4[1]=“followers”]
您真是太棒了,安德森爵士。多好的表情啊!!!可以用相同的元素创建css选择器来定位相同的东西吗?一个例子就足够了。谢谢。我不确定是否有办法将提供的XPath表达式转换为相同的CSS选择器。我知道有
符号表示即时的前面和前面的元素,但它们似乎还不支持……为了学习,安德森爵士在这一主题上还需要了解最后一件事。为什么是“h4[1]”,我的意思是为什么不在上面创建的xpath中索引[0]或[2]?对不起,我不知道。
h[1]
表示前面的第一个标题。请注意,在编程语言中,索引以
0
开头,而在XPath中,索引以
1
开头,这与此不同,非常有用。但是我不知道如何在我的代码中使用它。你能给我一个提示或者给我一个代码来使用吗?谢谢,它很有魅力。但是我不知道如何在我的代码中使用它。你能给我一个提示或者给我一个代码来使用吗?
//div[./preceding-sibling::h4[1]="Followed by"]//text()
//div[./preceding-sibling::h4[1]="Spin-off"]//text()
$ scrapy shell 'http://www.imdb.com/title/tt0092455/trivia?tab=mc&ref_=tt_trv_cnn'
(...)
>>> for cnt, h4 in enumerate(response.css('div.list > h4.li_group'), start=1):
...     print(cnt, h4.xpath('normalize-space()').get())
... 
1 Follows 
2 Followed by 
3 Edited into 
4 Spun-off from 
5 Spin-off 
6 Referenced in 
7 Featured in 
8 Spoofed in 
>>> for cnt, h4 in enumerate(response.css('div.list > h4.li_group'), start=1):
...     print(cnt, h4.xpath('normalize-space()').get())
...     print(h4.xpath('following-sibling::div[count(preceding-sibling::h4)=$cnt]',
                       cnt=cnt).xpath(
                          'string(.//a)').getall())
... 
1 Follows 
['Star Trek', 'Star Trek: The Animated Series', 'Star Trek: The Motion Picture', 'Star Trek II: The Wrath of Khan', 'Star Trek III: The Search for Spock', 'Star Trek IV: The Voyage Home']
2 Followed by 
['Star Trek V: The Final Frontier', 'Star Trek VI: The Undiscovered Country', 'Star Trek: Deep Space Nine', 'Star Trek: Generations', 'Star Trek: Voyager', 'First Contact', 'Star Trek: Insurrection', 'Star Trek: Enterprise', 'Star Trek: Nemesis', 'Star Trek', 'Star Trek Into Darkness', 'Star Trek Beyond', 'Star Trek: Discovery', 'Untitled Star Trek Sequel']
3 Edited into 
['Reading Rainbow: The Bionic Bunny Show', 'The Unauthorized Hagiography of Vincent Price']
4 Spun-off from 
['Star Trek']
5 Spin-off 
['Star Trek: The Next Generation - The Transinium Challenge', 'A Night with Troi', 'Star Trek: Deep Space Nine', "Star Trek: The Next Generation - Future's Past", 'Star Trek: The Next Generation - A Final Unity', 'Star Trek: The Next Generation: Interactive VCR Board Game - A Klingon Challenge', 'Star Trek: Borg', 'Star Trek: Klingon', 'Star Trek: The Experience - The Klingon Encounter']
6 Referenced in 
(...)
>>> item = {}
>>> for cnt, h4 in enumerate(response.css('div.list > h4.li_group'), start=1):
...     key = h4.xpath('normalize-space()').get().strip() # there are some non-breaking spaces
...     if key in ['Follows', 'Followed by', 'Spin-off']:
...         values = h4.xpath('following-sibling::div[count(preceding-sibling::h4)=$cnt]',
...                        cnt=cnt).xpath(
...                           'string(.//a)').getall()
...         item[key] = values
... 

>>> from pprint import pprint
>>> pprint(item)
{'Followed by': ['Star Trek V: The Final Frontier',
                 'Star Trek VI: The Undiscovered Country',
                 'Star Trek: Deep Space Nine',
                 'Star Trek: Generations',
                 'Star Trek: Voyager',
                 'First Contact',
                 'Star Trek: Insurrection',
                 'Star Trek: Enterprise',
                 'Star Trek: Nemesis',
                 'Star Trek',
                 'Star Trek Into Darkness',
                 'Star Trek Beyond',
                 'Star Trek: Discovery',
                 'Untitled Star Trek Sequel'],
 'Follows': ['Star Trek',
             'Star Trek: The Animated Series',
             'Star Trek: The Motion Picture',
             'Star Trek II: The Wrath of Khan',
             'Star Trek III: The Search for Spock',
             'Star Trek IV: The Voyage Home'],
 'Spin-off': ['Star Trek: The Next Generation - The Transinium Challenge',
              'A Night with Troi',
              'Star Trek: Deep Space Nine',
              "Star Trek: The Next Generation - Future's Past",
              'Star Trek: The Next Generation - A Final Unity',
              'Star Trek: The Next Generation: Interactive VCR Board Game - A '
              'Klingon Challenge',
              'Star Trek: Borg',
              'Star Trek: Klingon',
              'Star Trek: The Experience - The Klingon Encounter']}
>>>