尝试使用Scrapy从表格中提取数据
我正在使用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 个回答
要抓取数据,通常你需要先找到表格,然后逐行处理数据。
一个像这样的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()
首先,对于你想要的每一个符号,你需要知道与这个符号相关的名称。例如,对于“进球”这个符号,我看到有一个 <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>
列表的长度,输出对应数量的“进球”文本。
我刚刚看到页面链接,找到了你想要的所有比赛表格的行,使用了这个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
)。
一旦你获取了所有行,就可以遍历这些行,提取每一行中的所有信息。