如何发送另一个请求并在scrapy parse函数中获得结果?

时间:2018-11-13 10:29:07

标签: python scrapy web-crawler

我正在分析具有两个菜单的HTML页面。 顶级菜单更改后,将发送一个AJAX请求以获取第二级菜单项。当同时选择顶部和第二个菜单时,请刷新内容。

我需要的是发送另一个请求并在scrapy的parse函数中获得子菜单响应。因此,我可以迭代子菜单,为每个子菜单项构建scrapy.Request

这样的伪代码:

def parse(self, response):
    top_level_menu = response.xpath('//TOP_LEVEL_MENU_XPATH')
    second_level_menu_items = ## HERE I NEED TO SEND A REQUEST AND GET RESULT, PARSED TO ITME VALUE LIST

    for second_menu_item in second_level_menu_items:
        yield scrapy.Request(response.urljoin(content_request_url + '?top_level=' + top_level_menu + '&second_level_menu=' + second_menu_item), callback=self.parse_content)

我该怎么做?

直接使用requests lib?还是scrapy提供的其他功能?

2 个答案:

答案 0 :(得分:1)

这里推荐的方法是创建另一个回调(parse_second_level_menus?)以处理第二级菜单项的响应,然后在其中创建对内容页面的请求。

此外,您可以使用request.meta属性在回调方法(more info here)之间传递数据。

可能与以下内容有关:

def parse(self, response):
    top_level_menu = response.xpath('//TOP_LEVEL_MENU_XPATH').get()
    yield scrapy.Request(
        some_url,
        callback=self.parse_second_level_menus,
        # pass the top_level_menu value to the other callback
        meta={'top_menu': top_level_menu},
    )

def parse_second_level_menus(self, response):
    # read the data passed in the meta by the first callback
    top_level_menu = response.meta.get('top_menu')
    second_level_menu_items = response.xpath('...').getall()

    for second_menu_item in second_level_menu_items:
        url = response.urljoin(content_request_url + '?top_level=' + top_level_menu + '&second_level_menu=' + second_menu_item)
        yield scrapy.Request(
            url,
            callback=self.parse_content
    )

def parse_content(self, response):
    ...

另一种方法(在这种情况下不建议使用)将使用以下库:https://github.com/rmax/scrapy-inline-requests

答案 1 :(得分:0)

仅对您的请求使用dont_filter = True 例如:

def start_requests(self):
    return [Request(url=self.base_url, callback=self.parse_city)]

def parse_city(self, response):
    for next_page in response.css('a.category'):
        url = self.base_url + next_page.attrib['href']
        self.log(url)
        yield Request(url=url,  callback=self.parse_something_else, dont_filter=True)

def parse_something_else(self, response):
    for next_page in response.css('#contentwrapper > div > div > div.component > table > tbody > tr:nth-child(2) > td > form > table > tbody > tr'):
        url = self.base_url + next_page.attrib['href']
        self.log(url)
        yield Request(url=next_page, callback=self.parse, dont_filter=True)

def parse(self, response):
    pass