Scrapy使用xpath将多个项目元素输出到单个csv?

Scrapy使用xpath将多个项目元素输出到单个csv?,csv,xpath,web-scraping,scrapy,Csv,Xpath,Web Scraping,Scrapy,我试图从一个包含各种HTML元素和一系列嵌套表的页面中删除项目 我有一些代码可以成功地从class=“ClassA”所在的表X中删除,并将表元素输出到一系列项目中,如公司地址、电话号码、网站地址等 我想将一些额外的项目添加到我正在输出的列表中,但是其他要刮除的项目不在同一个表中,有些甚至根本不在表中,例如页面另一部分的标记 如何使用xpath筛选器将其他项目添加到我的输出中,并使它们显示在相同的数组/输出结构中?我注意到,如果我从另一个表中刮取额外的表项(即使该表具有完全相同的类名和ID),这些

我试图从一个包含各种HTML元素和一系列嵌套表的页面中删除项目

我有一些代码可以成功地从class=“ClassA”所在的表X中删除,并将表元素输出到一系列项目中,如公司地址、电话号码、网站地址等

我想将一些额外的项目添加到我正在输出的列表中,但是其他要刮除的项目不在同一个表中,有些甚至根本不在表中,例如页面另一部分的

标记

如何使用xpath筛选器将其他项目添加到我的输出中,并使它们显示在相同的数组/输出结构中?我注意到,如果我从另一个表中刮取额外的表项(即使该表具有完全相同的类名和ID),这些其他项的CSV输出将在CSV中的不同行上输出,而不会保持CSV结构完整:(

我确信必须有一种方法使项目在csv输出中保持统一,即使它们是从页面上稍微不同的区域刮取的?希望这只是一个简单的修复

-----正在刮取的HTML示例页面-----

输出到CSV

scrapy crawl my -o items.csv -t csv
在上面的示例代码中,[company mission]项在CSV中显示在与其他项不同的行上(猜测,因为它在不同的表中),即使它具有相同的类名和ID,而且我不确定如何刮除

字段,因为它不在我当前XPATH站点筛选器的表结构中

我可以扩展站点XPATH过滤器以包含更多内容,但这会不会降低效率,并破坏所有过滤点

这里是调试日志的一个示例,您可以看到公司任务由于某种原因被处理了两次,并且第一个循环是空的,这一定是它输出到CSV中新行的原因,但为什么

{'Item_Code': [u'ABC'],
 'Listing_Date': [u'1 January, 2000'],
 'Office_Address': [u'Level 1, Some Street, SYDNEY, NSW, AUSTRALIA, 2000'],
 'Office_Fax': [u'(02) 1234 5678'],
 'Office_Phone': [u'(02) 1234 5678'],
 'Company_Mission': [],
 'Website_URL': [u'http://www.company.com']}
2014-02-06 16:32:13+1000 [my] DEBUG: Scraped from <200 http://www.website.com/Code=ABC>
{'Item_Code': [],
 'Listing_Date': [],
 'Office_Address': [],
 'Office_Fax': [],
 'Office_Phone': [],
 'Company_Mission': [u'The comapany is involved in retail, food and beverage, wholesale services.'],
 'Website_URL': []}
{'Item_code':[u'ABC'],
'上市日期':[u'2000年1月1日'],
“办公地址”:[2000年,澳大利亚新南威尔士州悉尼市某街1楼],
‘办公室传真’:[u’(02)12345678'],
"办公室电话:[u(02)1234 5678'],,
“公司使命”:[],
“网站URL”:[u'http://www.company.com']}
2014-02-06 16:32:13+1000[我的]调试:从
{'Item_Code':[],
“上市日期”:[],
“办公室地址”:[],
“办公室传真”:[],
“办公室电话”:[],
“公司使命”:[公司从事零售、餐饮、批发服务。],
“网站URL:[]]

另一件我完全困惑的事情是,为什么CSV中的项目以与HTML页面上的项目以及我在spiders配置文件中定义的顺序完全不同的顺序吐出。scrapy是否完全异步运行,以任意顺序返回项目?

猜测,因为它位于不同的选项卡中le
-猜错了,表格和项目之间没有相关性,事实上,数据从哪里来并不重要,只要您在项目字段中设置它

这意味着你可以从任何你想去的地方取公司的名字和公司的使命


话虽如此,请检查从
//th[text()=“Company Mission”]
返回的内容以及它在页面上出现的次数,而其他项目是相对的(以
开头),这一项是绝对的(以
///code>开头),它可能会刮除一个项目列表,而不仅仅是一个项目。

我知道您希望为此页面刮除一个项目,但是
//table[@class=“contenttable company details”]
匹配HTML内容中的两个tables元素,因此
for site in sites:
将运行两次,创建两个项目

对于每个表,如果XPath表达式是相对的--
//th[text()=“Item code”]
,则它们将应用于当前表中。绝对XPath表达式,例如
//th[text()=“Company Mission”]
,将从HTML文档的根元素中查找元素

您的示例输出只显示了一次
“Company\u Mission”
,而您说它出现了两次。而且因为您使用的是绝对XPath表达式,所以它确实出现了两次。不确定输出是否与问题中当前的spider代码匹配

循环的第一次迭代

    <table cellspacing="0" class="contenttable company-details">
    <tr>
      <th>Item Code</th>
      <td>IT123</td>
    </tr>
      <th>Listing Date</th>
      <td>12 September, 2011</td>
    </tr>
    <tr>
      <th>Internet Address</th>
      <td class="altrow"><a href="http://www.website.com/" target="_top">http://www.website.com/</a></td>
    </tr>
    <tr>
      <th>Office Address</th>
      <td>123 Example Street</td>
    </tr>    
    <tr>
      <th>Office Telephone</th>
      <td>(01) 1234 5678</td>
    </tr>       
    </table>
对于它,实例化了一个新的
MyItem()
,在这里,除了“Company Mission”的绝对XPath之外,没有任何XPath表达式匹配,因此在循环迭代结束时,您得到了一个只有“Company Mission”的项

如果您确定此页面中只需要1项,并且只需要1项,则可以使用更长的XPath,如
//table[@class=“contenttable company details”]///th[text()=“item code”]/以下同级::td//text()
,以匹配所需的每个字段的第一个或第二个表

并且只使用1
MyItem()
实例

此外,您还可以尝试读写时间更短、更易于维护的CSS选择器:


  • “Company_name”所以我尝试了//th[text()=“Company Mission”]带绝对值(点)和不带绝对值(点),但两者都会导致CSV“Company Mission”要输出到新行的项目,在所有其他CSV项目仅在现有行上用逗号分隔之后。仍然不清楚为什么会发生这种情况?感谢Paul,这对于为什么循环在表元素出现两次后运行两次更为合理:-)我已经按照您的建议将每个项目设置为使用较长的XPath选择器,并且还调整了sites变量以引用文档中只出现一次的元素,因此现在它只循环一次。事情看起来不错!
    {'Item_Code': [u'ABC'],
     'Listing_Date': [u'1 January, 2000'],
     'Office_Address': [u'Level 1, Some Street, SYDNEY, NSW, AUSTRALIA, 2000'],
     'Office_Fax': [u'(02) 1234 5678'],
     'Office_Phone': [u'(02) 1234 5678'],
     'Company_Mission': [],
     'Website_URL': [u'http://www.company.com']}
    2014-02-06 16:32:13+1000 [my] DEBUG: Scraped from <200 http://www.website.com/Code=ABC>
    {'Item_Code': [],
     'Listing_Date': [],
     'Office_Address': [],
     'Office_Fax': [],
     'Office_Phone': [],
     'Company_Mission': [u'The comapany is involved in retail, food and beverage, wholesale services.'],
     'Website_URL': []}
    
        <table cellspacing="0" class="contenttable company-details">
        <tr>
          <th>Item Code</th>
          <td>IT123</td>
        </tr>
          <th>Listing Date</th>
          <td>12 September, 2011</td>
        </tr>
        <tr>
          <th>Internet Address</th>
          <td class="altrow"><a href="http://www.website.com/" target="_top">http://www.website.com/</a></td>
        </tr>
        <tr>
          <th>Office Address</th>
          <td>123 Example Street</td>
        </tr>    
        <tr>
          <th>Office Telephone</th>
          <td>(01) 1234 5678</td>
        </tr>       
        </table>
    
        <table cellspacing="0" class="contenttable company-details">    
        <tr>
            <th>Contact Person</th>
            <td>        
            Mr John Citizen<br/>        
            </td>
        </tr>   
        <tr>
            <th class=principal>Company Mission</th>
            <td>ACME Corp is a retail sales company.</td>
        </tr>   
        </table>