尝试使用Scrapy从表格中提取数据

1 投票
3 回答
7839 浏览
提问于 2025-04-18 13:08

我正在使用Python.org的2.7 64位版本,系统是Vista 64位。我现在有一段Scrapy代码,能够很好地提取文本,但我在从网站的表格中获取数据时遇到了一些困难。我在网上查了一些资料,但还是不太明白。举个例子,我想获取这个表格中关于韦恩·鲁尼进球统计的数据:

http://www.whoscored.com/Players/3859/Fixtures/Wayne-Rooney

我现在的代码是这样的:

from scrapy.spider import Spider
from scrapy.selector import Selector
from scrapy.utils.markup import remove_tags
from scrapy.cmdline import execute
import re


class MySpider(Spider):
    name = "Goals"
    allowed_domains = ["whoscored.com"]
    start_urls = ["http://www.whoscored.com/Players/3859/Fixtures/Wayne-Rooney"]

    def parse(self, response):
        titles = response.selector.xpath("normalize-space(//title)")
        for titles in titles:

            body = response.xpath("//p").extract()
            body2 = "".join(body)

            print remove_tags(body2).encode('utf-8')

execute(['scrapy','crawl','goals'])

我在xpath()语句中需要使用什么语法才能获取表格数据呢?

谢谢

3 个回答

0

要抓取数据,通常你需要先找到表格,然后逐行处理数据。

一个像这样的html表格通常有这样的格式:

<table id="thistable">
  <tr>
    <th>Header1</th>
    <th>Header2</th>
  </tr>
  <tr>
    <td>data1</td>
    <td>data2</td>
  </tr>
</table>

下面是一个解析这个比赛表的例子:

from scrapy.spider import Spider
from scrapy.http import Request
from myproject.items import Fixture

class GoalSpider(Spider):
    name = "goal"
    allowed_domains = ["whoscored.com"]
    start_urls = (
        'http://www.whoscored.com/',
        )

    def parse(self, response):
        return Request(
            url="http://www.whoscored.com/Players/3859/Fixtures/Wayne-Rooney",
            callback=self.parse_fixtures
        )

    def parse_fixtures(self,response):
        sel = response.selector
        for tr in sel.css("table#player-fixture>tbody>tr"):
             item = Fixture()
             item['tournament'] = tr.xpath('td[@class="tournament"]/span/a/text()').extract()
             item['date'] = tr.xpath('td[@class="date"]/text()').extract()
             item['team_home'] = tr.xpath('td[@class="team home "]/a/text()').extract()
             yield item

首先,我用 sel.css("table#player-fixture>tbody>tr") 来找到数据行,然后对结果进行循环,接着提取数据。

补充说明:items.py (http://doc.scrapy.org/en/latest/topics/items.html)

class Fixture(Item):
    tournament = Field()
    date = Field()
    team_home = Field()
0

首先,对于你想要的每一个符号,你需要知道与这个符号相关的名称。例如,对于“进球”这个符号,我看到有一个 <span> 元素,它的 title 属性是 "Goal",还有一个 <span> 元素,它的 title 属性是 "Assist",表示“助攻”。

根据这些信息,你可以检查每一行数据,看看里面是否包含一个 title 属性是你想要的符号名称的 <span> 元素。

要获取一行中的所有“进球”符号,你可以使用这个表达式来检查: //span[@title="Goal",如下所示:

for row in response.selector.xpath(
            '//table[@id="player-fixture"]//tr[td[@class="tournament"]]'):
    # Is this row contains goal symbols?
    list_of_goals = row.xpath('//span[@title="Goal"')
    if list_of_goals:
        # Output goals text.
    .
    .
    .

如果返回的列表不是空的,那就说明这一行里有“进球”符号。所以,你可以根据返回的 <span> 列表的长度,输出对应数量的“进球”文本。

3

我刚刚看到页面链接,找到了你想要的所有比赛表格的行,使用了这个Xpath表达式:'//table[@id="player-fixture"]//tr[td[@class="tournament"]]'

我来给你解释一下这个Xpath表达式的每个部分:

  • //table[@id="player-fixture"]:这个部分是用来获取整个表格,表格的ID是player-fixture,你可以在页面上查看到这个。
  • //tr[td[@class="tournament"]]:这个部分是用来获取所有包含比赛信息的行。

你也可以只用这个更简短的//tr[td[@class="tournament"]]表达式。但我觉得使用前面的表达式更好,因为这样你明确表示想要在特定的表格下获取所有行(tr),而这个表格的ID是唯一的(player-fixture)。

一旦你获取了所有行,就可以遍历这些行,提取每一行中的所有信息。

撰写回答