Xpath Scrapy-从表中提取项目

Xpath Scrapy-从表中提取项目,xpath,scrapy,Xpath,Scrapy,试着让我的头绕着痒痒,但碰到了一些死胡同 我在一个页面上有两个表,我想从每个表中提取数据,然后移动到下一个页面 表看起来像这样(第一个称为Y1,第二个称为Y2),结构相同 <div id="Y1" style="margin-bottom: 0px; margin-top: 15px;"> <h2>First information</h2><hr style="margin-top: 5p

试着让我的头绕着痒痒,但碰到了一些死胡同

我在一个页面上有两个表,我想从每个表中提取数据,然后移动到下一个页面

表看起来像这样(第一个称为Y1,第二个称为Y2),结构相同

<div id="Y1" style="margin-bottom: 0px; margin-top: 15px;">
                                <h2>First information</h2><hr style="margin-top: 5px; margin-bottom: 10px;">                    

                <table class="table table-striped table-hover table-curved">
                    <thead>
                        <tr>
                            <th class="tCol1" style="padding: 10px;">First Col Head</th>
                            <th class="tCol2" style="padding: 10px;">Second Col Head</th>
                            <th class="tCol3" style="padding: 10px;">Third Col Head</th>
                        </tr>
                    </thead>
                    <tbody>

                        <tr>
                            <td>Info 1</td>
                            <td>Monday 5 September, 2016</td>
                            <td>Friday 21 October, 2016</td>
                        </tr>
                        <tr class="vevent">
                            <td class="summary"><b>Info 2</b></td>
                            <td class="dtstart" timestamp="1477094400"><b></b></td>
                            <td class="dtend" timestamp="1477785600">
                            <b>Sunday 30 October, 2016</b></td>
                        </tr>
                        <tr>
                            <td>Info 3</td>
                            <td>Monday 31 October, 2016</td>
                            <td>Tuesday 20 December, 2016</td>
                        </tr>


                    <tr class="vevent">
                        <td class="summary"><b>Info 4</b></td>                      
                        <td class="dtstart" timestamp="1482278400"><b>Wednesday 21 December, 2016</b></td>
                        <td class="dtend" timestamp="1483315200">
                        <b>Monday 2 January, 2017</b></td>
                    </tr>



                </tbody>
            </table>
这里没有错误,但它只是返回了大量有关爬网的信息,但没有实际结果

更新:

  import scrapy

       class SchoolSpider(scrapy.Spider):
name = "school"

allowed_domains = ["termdates.co.uk"]
start_urls =    (
                'https://termdates.co.uk/school-holidays-16-19-abingdon/',
                )

  def parse_products(self, response):
  products = sel.xpath('//*[@id="Year1"]/table//tr')
 for p in products[1:]:
  item = dict()
  item['hol'] = p.xpath('td[1]/text()').extract_first()
  item['first'] = p.xpath('td[1]/text()').extract_first()
  item['last'] = p.xpath('td[1]/text()').extract_first()
  yield item
这给了我:缩进错误:意外缩进

如果我运行下面的修改脚本(感谢@Granitosaurus)以输出到CSV(-o schoolDates.CSV),我会得到一个空文件:

import scrapy

class SchoolSpider(scrapy.Spider):
name = "school"
allowed_domains = ["termdates.co.uk"]
start_urls = ('https://termdates.co.uk/school-holidays-16-19-abingdon/',)

def parse_products(self, response):
    products = sel.xpath('//*[@id="Year1"]/table//tr')
    for p in products[1:]:
        item = dict()
        item['hol'] = p.xpath('td[1]/text()').extract_first()
        item['first'] = p.xpath('td[1]/text()').extract_first()
        item['last'] = p.xpath('td[1]/text()').extract_first()
        yield item
这是日志:

  • 2017-03-23 12:04:08[刮屑芯发动机]信息:十字轴已打开 2017-03-23 12:04:08[scrapy.extensions.logstats]信息:已爬网0 页数(以0页/分钟的速度),刮取0项(以0项/分钟的速度)2017-03-23 12:04:08[scrapy.extensions.telnet]调试:telnet控制台侦听 在…上2017-03-23 12:04:08[刮屑核心引擎]调试:爬网(200) https://termdates.co.uk/robots.txt>(推荐人:无)2017-03-23 12:04:08[scrapy.core.engine]调试:已爬网(200)https://termdates.co.uk/school-holidays-16-19-abingdon/>(参考: 无)2017-03-23 12:04:08[scrapy.core.scraper]错误:十字轴错误 处理https://termdates.co.uk/school-holidays-16-19-abingdon/>(参考: 无)回溯(最近一次呼叫最后一次):文件 “c:\python27\lib\site packages\twisted\internet\defer.py”,第653行, 运行中回调 current.result=callback(current.result,*args,**kw)文件“c:\python27\lib\site packages\scrapy-1.3.3-py2.7.egg\scrapy\spider\uuuuu init\uuuuu.py”, 第76行,在语法分析中 升起未执行错误未执行错误2017-03-23 12:04:08[刮屑.堆芯.发动机]信息:关闭卡盘(完成)2017-03-23 12:04:08[scrapy.statscollectors]信息:转储scrapy统计信息: {'downloader/request_bytes':467,'downloader/request_count':2, “下载器/请求\方法\计数/获取”:2, “下载/响应字节”:11311,“下载/响应计数”:2, “下载/响应\状态\计数/200”:2,“完成\原因”: “完成”、“完成时间”:datetime.datetime(2017,3,23,12,4,8, 845000),“日志计数/调试”:3,“日志计数/错误”:1, “日志计数/信息”:7,“响应计数”:2, “调度程序/出列”:1,“调度程序/出列/内存”:1, “调度程序/排队”:1,“调度程序/排队/内存”:1, “蜘蛛异常/未实现错误”:1,“开始时间”: datetime.datetime(2017,3,23,12,4,8356000)}2017-03-23 12:04:08 [scrapy.core.engine]信息:十字轴关闭(完成)
更新2:(跳过行) 这会将结果推送到csv文件,但会每隔一行跳过一次

外壳显示 {'hol':无,'last':u'\r\n\t\t\t\t\t\t','first':无}

import scrapy

class SchoolSpider(scrapy.Spider):
name = "school"
allowed_domains = ["termdates.co.uk"]
start_urls = ('https://termdates.co.uk/school-holidays-16-19-abingdon/',)

def parse(self, response):
    products = response.xpath('//*[@id="Year1"]/table//tr')
    for p in products[1:]:
        item = dict()
        item['hol'] = p.xpath('td[1]/text()').extract_first()
        item['first'] = p.xpath('td[2]/text()').extract_first()
        item['last'] = p.xpath('td[3]/text()').extract_first()
        yield item
解决方案:多亏了@strong>vold 这将爬网start_URL中的所有页面,并处理不一致的表布局

# -*- coding: utf-8 -*-
import scrapy
from SchoolDates_1.items import Schooldates1Item

class SchoolSpider(scrapy.Spider):
name = "school"
allowed_domains = ["termdates.co.uk"]
start_urls = ('https://termdates.co.uk/school-holidays-16-19-abingdon/',
              'https://termdates.co.uk/school-holidays-3-dimensions',)

def parse(self, response):
    products = response.xpath('//*[@id="Year1"]/table//tr')
    # ignore the table header row
    for product in products[1:]:
        item = Schooldates1Item()
        item['hol'] = product.xpath('td[1]//text()').extract_first()
        item['first'] = product.xpath('td[2]//text()').extract_first()
        item['last'] = ''.join(product.xpath('td[3]//text()').extract()).strip()
        item['url'] = response.url
        yield item

您需要稍微更正代码。由于已经选择了表中的所有元素,因此无需再次指向表。因此,您可以将xpath缩短为如下内容
td[1]//text()


编辑了我的答案,因为@stutray提供了指向站点的链接。

我使用这些XPath获得了您提供的html源代码:

products = sel.xpath('//*[@id="Y1"]/table//tr')
for p in products[1:]:
    item = dict()
    item['hol'] = p.xpath('td[1]/text()').extract_first()
    item['first'] = p.xpath('td[1]/text()').extract_first()
    item['last'] = p.xpath('td[1]/text()').extract_first()
    yield item

上面假设每个表行包含1项。

您可以使用CSS选择器而不是XPath,我总是觉得CSS选择器很简单

def parse_products(self, response):

    for table in response.css("#Y1 table")[1:]:
       item = Schooldates1Item()
       item['hol'] = product.css('td:nth-child(1)::text').extract_first()
       item['first'] = product.css('td:nth-child(2)::text').extract_first()
       item['last'] = product.css('td:nth-child(3)::text').extract_first()
       yield item
也不要在选择器中使用
t正文
标记

Firefox尤其以向表中添加元素而闻名。另一方面,Scrapy不会修改原始页面HTML,因此如果在XPath表达式中使用,则无法提取任何数据


请提供更多信息:您尝试了什么?什么代码?哪个XPATH表达式让您感到困惑?你有没有读过关于这个问题的教程?嗨,埃尔顿,我已经在上面添加了我的最新代码。谢谢。你能提供你想要解析的站点的链接吗?另外,请尝试在xpath表达式中不使用
tbody
。@vold不使用tbody的原因是什么?这似乎是避免分析标题行的一种明显方法。@stutray tbody是由Mozilla和Chrome等浏览器添加的,它不存在于原始HTML源代码中。
/
在这里不是必需的,因为表达式已绑定到第一级。如果要查找任何后代,实际上需要使用
/
。另外,
extract_first()
是相对较新的
extract(),所以您的xpath不起作用。@Umair在OP的代码上下文中它会起作用:P。您还暗示OP不使用浏览器或某些渲染来下载源代码。因此,在这个问题的背景下,我的原始答案是可行的,但还是调整了answet以反映您的观点。谢谢各位的意见。请查看我的编辑,我正在尝试快速提问-为什么每个xpath都是
td[1]
-是否
td
s被
删除。extract_first()
使用css或xpath没有区别,在这种情况下xpath更直接,例如
td[1]
products = sel.xpath('//*[@id="Y1"]/table//tr')
for p in products[1:]:
    item = dict()
    item['hol'] = p.xpath('td[1]/text()').extract_first()
    item['first'] = p.xpath('td[1]/text()').extract_first()
    item['last'] = p.xpath('td[1]/text()').extract_first()
    yield item
def parse_products(self, response):

    for table in response.css("#Y1 table")[1:]:
       item = Schooldates1Item()
       item['hol'] = product.css('td:nth-child(1)::text').extract_first()
       item['first'] = product.css('td:nth-child(2)::text').extract_first()
       item['last'] = product.css('td:nth-child(3)::text').extract_first()
       yield item