【问题标题】:Scrapy in Python order extract with xpaths使用 xpaths 以 Python 顺序提取的 Scrapy
【发布时间】:2020-04-24 13:47:07
【问题描述】:

我正在使用 Python 中的蜘蛛从页面中抓取一些文本,输出是一个 .csv 文件。除了一些记录的顺序之外,一切都可以,它在 .csv 文件中的生成顺序与我在 spider.py 中的顺序不同:

这是我得到的:

但这是我需要的顺序并且我传递给 spider.py(颜色的行是倒置的):

我不知道为什么它不尊重数据抓取的顺序。出于某种原因,它尊重数据在网页中出现的相同顺序,但如果我以与网络不同的顺序传递它,为什么蜘蛛会忽略我?

我的代码:

import scrapy
from scrapy.spiders import Spider
from scrapy.linkextractors import LinkExtractor
from scrapy.exceptions import CloseSpider
from verbos.items import MercadoItem

class MercadoSpider(scrapy.Spider):
name = 'verbos'
allowed_domain = ['www.pt.bab.la']
print("Ingrese un verbo:")
variable = input()
start_urls = ['https://pt.bab.la/verbo/portugues/' + variable]


def parse(self, response):

    eu = response.xpath('//*[@id="conjFull"]/div[2]/div/div[2]/div[1]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[4]/div[1]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[3]/div[1]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[5]/div[1]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[6]/div[1]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[8]/div[1]/div[2]/text() | //*[@class="content-column"]/div[3]/div[1]/div[1]/div[2]/div[1]/div[2]/text() | //*[@class="content-column"]/div[3]/div[1]/div[1]/div[3]/div[1]/div[2]/text() | //*[@class="content-column"]/div[6]/div[1]/div[1]/div[2]/div[1]/div[2]/text() | //*[@class="content-column"]/div[5]/div[1]/div[1]/div[2]/div[1]/div[2]/text()').extract()
    voce = response.xpath('//*[@id="conjFull"]/div[2]/div/div[2]/div[3]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[4]/div[3]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[3]/div[3]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[5]/div[3]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[6]/div[3]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[8]/div[3]/div[2]/text() | //*[@class="content-column"]/div[3]/div[1]/div[1]/div[2]/div[3]/div[2]/text() | //*[@class="content-column"]/div[3]/div[1]/div[1]/div[3]/div[3]/div[2]/text() | //*[@class="content-column"]/div[6]/div[1]/div[1]/div[2]/div[1]/div[2]/text() | //*[@class="content-column"]/div[5]/div[1]/div[1]/div[2]/div[1]/div[2]/text()').extract()
    nos = response.xpath('//*[@id="conjFull"]/div[2]/div/div[2]/div[4]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[4]/div[4]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[3]/div[4]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[5]/div[4]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[6]/div[4]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[8]/div[4]/div[2]/text() | //*[@class="content-column"]/div[3]/div[1]/div[1]/div[2]/div[4]/div[2]/text()  | //*[@class="content-column"]/div[3]/div[1]/div[1]/div[3]/div[4]/div[2]/text() | //*[@class="content-column"]/div[6]/div[1]/div[1]/div[2]/div[1]/div[2]/text() | //*[@class="content-column"]/div[5]/div[1]/div[1]/div[2]/div[1]/div[2]/text()').extract()
    voces = response.xpath('//*[@id="conjFull"]/div[2]/div/div[2]/div[6]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[4]/div[6]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[3]/div[6]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[5]/div[6]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[6]/div[6]/div[2]/text() | //*[@id="conjFull"]/div[2]/div/div[8]/div[6]/div[2]/text() | //*[@class="content-column"]/div[3]/div[1]/div[1]/div[2]/div[6]/div[2]/text()  | //*[@class="content-column"]/div[3]/div[1]/div[1]/div[3]/div[6]/div[2]/text() | //*[@class="content-column"]/div[6]/div[1]/div[1]/div[2]/div[1]/div[2]/text() | //*[@class="content-column"]/div[5]/div[1]/div[1]/div[2]/div[1]/div[2]/text()').extract()

    for item in zip(eu, voce, nos, voces):
        scraped_info = {
            'eu' : item[0],
            'voce' : item[1],
            'nos' : item[2],
            'voces' : item[3],
        }

        yield scraped_info

items.py:

import scrapy


class MercadoItem(scrapy.Item):
eu = scrapy.Field()
voce = scrapy.Field()
nos = scrapy.Field()
voces  = scrapy.Field()

settings.py:

BOT_NAME = 'verbos'

SPIDER_MODULES = ['verbos.spiders']
NEWSPIDER_MODULE = 'verbos.spiders'

ITEM_PIPELINES = {'verbos.pipelines.MercadoPipeline': 500}
FEED_FORMAT = "csv"
FEED_URI = 'verbos_items.csv'
FEED_EXPORT_ENCODING='cp1252'

ROBOTSTXT_OBEY = False

【问题讨论】:

    标签: python csv scrapy


    【解决方案1】:

    XPath 表达式只确定匹配,而不是顺序。

    不要使用单个 XPath 表达式,而是在循环中按所需顺序迭代每个 XPath 表达式。

    所以,改变:

    words = response.xpath('xpath1 | xpath2').getall()
    for word in words:
        yield {'word': word}
    

    收件人:

    for xpath in ('xpath1', 'xpath2'):
        words = response.xpath(xpath).getall()
        for word in words:
            yield {'word': word}
    

    【讨论】:

    • 我只尝试了“eu”列并且有效!现在我按照我想要的顺序得到它,但是我怎么能添加其他 3 列呢?如果您需要,我可以编辑代码
    • 您可以在外部 for 循环中使用 xpath 元组的元组而不是元组。或者,如果 XPath 表达式遵循某种模式,您可以使用字符串格式使其更简单。但是现在您了解了为什么它没有按预期工作,您应该能够弄清楚如何使它工作。
    猜你喜欢
    • 1970-01-01
    • 2014-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-22
    • 2020-05-31
    相关资源
    最近更新 更多