【问题标题】:scrapy - item loader - mysqlscrapy - 项目加载器 - mysql
【发布时间】:2016-10-08 16:10:32
【问题描述】:

我开始学习scrapy。我想使用一个项目加载器并将一些数据写入 MySQL。当我在 items.py 中为输出处理器使用参数“TakeFirst()”时,下面的代码工作得非常好。但是,我需要获取 MySQL 的所有条目,而不仅仅是第一个。当我改用参数“MapCompose()”时,我收到以下与 MySQL 相关的错误消息:

错误 1241:操作数应包含 1 列

如何修改我的代码以将所有条目写入 MySQL?

test_crawlspider.py:

import scrapy
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from tutorial.items import TestItem
from scrapy.loader import ItemLoader

class TestCrawlSpider(CrawlSpider):
    name = "test_crawl"
    allowed_domains = ["www.immobiliare.it"]
    start_urls = [
        "http://www.immobiliare.it/Roma/case_in_vendita-Roma.html?criterio=rilevanza"
    ]

    rules = (
        Rule(SgmlLinkExtractor(allow=(), restrict_xpaths=('//a[@class="no-decoration button next_page_act"]',)), callback="parse_start_url", follow= True),
    )

    handle_httpstatus_list = [302]

    def parse_start_url(self, response):
        l = ItemLoader(item=TestItem(), response=response)
        l.add_xpath('price', '//*/div[1]/div[1]/div[4]/strong/text()')
        l.add_xpath('rooms', '//*/div[1]/div[1]/div[7]/div[1]/span[4]/text()')
        return l.load_item()

items.py:

import scrapy
from scrapy.loader import ItemLoader
from scrapy.loader.processors import TakeFirst, MapCompose, Join


class TestItem(scrapy.Item):
    price = scrapy.Field(
        output_processor=TakeFirst(),
    )
    rooms = scrapy.Field(
        output_processor=TakeFirst(),
    )

pipelines.py:

import sys
import MySQLdb
import hashlib
from scrapy.http import Request
from tutorial.items import TestItem    

class MySQLPipeline(object):

    def __init__(self):
        self.conn = MySQLdb.connect(user='XXX', passwd='YYY', host='localhost', db='ZZZ')
        self.cursor = self.conn.cursor()

    def process_item(self, item, test_crawl):  
        print item
        return item
        try:
            self.cursor.execute("INSERT INTO test_table (price, rooms) VALUES (%s, %s)", (item['price'], item['rooms']))       
            self.conn.commit()

        except MySQLdb.Error, e:
            print "Error %d: %s" % (e.args[0], e.args[1])
            return item

【问题讨论】:

    标签: python mysql scrapy


    【解决方案1】:

    您需要将string 值传递给mysql,这就是TakeFirst() 起作用的原因,因为它会转换您在加载程序中获得的列表,并且只获取第一个元素(这是正常过程,因为它通常会获取像['myvalue'] 这样的工作人员在这种情况下完全可以只获取第一个元素)。

    现在如果你想在你的数据库中输入一个列表,比如['a', 'b', 'c'],你需要定义如何将它序列化为一个字符串,例如:

     'a;b;c' # join the list elements with ';' -> ';'.join(['a', 'b', 'c'])
    

    这是您需要定义的内容,因为稍后从数据库中查询时,您必须相应地对其进行去串化:

     'a;b;c'.split(';') -> ['a' ,'b', 'c']
    

    要使用我的示例,您可以在 loader 上使用类似的东西:

    class TestItem(scrapy.Item):
        price = scrapy.Field(
            output_processor=Join(';'),
        )
        rooms = scrapy.Field(
            output_processor=Join(';'),
        )
    

    【讨论】:

    • 感谢您的回答。虽然这会将数据写入 MySQL,但我希望将列表中的每个元素放在单独的行中。
    【解决方案2】:

    您需要为列表中的每个条目创建一个项目,如下所示:

    import scrapy
    from scrapy.loader import ItemLoader
    from scrapy.spiders import CrawlSpider, Rule
    from scrapy.linkextractors import LinkExtractor
    
    
    class TestCrawlSpider(CrawlSpider):
        name = "test_crawl"
        allowed_domains = ["www.immobiliare.it"]
        start_urls = [
            "http://www.immobiliare.it/Roma/case_in_vendita-Roma.html?criterio=rilevanza"
        ]
    
        rules = (
            Rule(LinkExtractor(allow=(), restrict_xpaths=('//a[@class="no-decoration button next_page_act"]',)), callback="parse_start_url", follow= True),
        )
    
        handle_httpstatus_list = [302]
    
        def parse_start_url(self, response):
            for selector in response.css('div.content'):
                l = ItemLoader(item=TestItem(), selector=selector)
                l.add_css('price', '.price::text')
                l.add_css('rooms', '.bottom::text, .bottom span::text', re=r'.*locali.*')
                yield l.load_item()
    

    我对选择器进行了一些更改,以便您可以检查其他可能性(同时了解 scrapy),但这可能不是您想要提取的信息。

    【讨论】:

    • 谢谢,我正在寻找这个解决方案。
    猜你喜欢
    • 2014-10-03
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 2019-02-18
    • 2020-07-24
    相关资源
    最近更新 更多