【问题标题】:scrapy crawl spider ajax paginationscrapy crawl spider ajax 分页
【发布时间】:2015-02-14 14:15:38
【问题描述】:

我试图废弃有 ajax 要求分页的链接。 我正在尝试抓取http://www.demo.com 链接。在 .py 文件中,我提供了限制 XPATH 的代码,编码是:

# -*- coding: utf-8 -*-
import scrapy

from scrapy.contrib.linkextractors import LinkExtractor
from scrapy.contrib.spiders import sumSpider, Rule
from scrapy.selector import HtmlXPathSelector
from sum.items import sumItem

class Sumspider1(sumSpider):
    name = 'sumDetailsUrls'
    allowed_domains = ['sum.com']
    start_urls = ['http://www.demo.com']
    rules = (
        Rule(LinkExtractor(restrict_xpaths='.//ul[@id="pager"]/li[8]/a'), callback='parse_start_url', follow=True),
    )

    #use parse_start_url if your spider wants to crawl from first page , so overriding 
    def parse_start_url(self, response):
        print '********************************************1**********************************************'
        #//div[@class="showMoreCars hide"]/a
        #.//ul[@id="pager"]/li[8]/a/@href
        self.log('Inside - parse_item %s' % response.url)
        hxs = HtmlXPathSelector(response)
        item = sumItem()
        item['page'] = response.url
        title = hxs.xpath('.//h1[@class="page-heading"]/text()').extract() 
        print '********************************************title**********************************************',title
        urls = hxs.xpath('.//a[@id="linkToDetails"]/@href').extract()
        print '**********************************************2***url*****************************************',urls

        finalurls = []       

        for url in urls:
            print '---------url-------',url
            finalurls.append(url)          

        item['urls'] = finalurls
        return item

我的 items.py 文件包含

from scrapy.item import Item, Field


class sumItem(Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    page = Field()
    urls = Field()

当我抓取它时,我仍然没有得到准确的输出,无法获取所有页面。

【问题讨论】:

  • 如果网页的某些部分是通过使用 JavaScript 检索的内容呈现的,您需要在解析之前使用 JavaScript 引擎呈现整个页面。也许你应该看看seleniumhq.org
  • 亲爱的 Jonatan,如果您不介意,请您举例说明一下,因为我是初学者。
  • 很遗憾,我手头没有示例。但是根据您的描述,您的问题似乎是在开始解析时网页没有完全生成,因此您需要在解析之前处理网页中的 JavaScript。一种方法是使用完整的浏览器,这就是我建议使用 Selenium 的原因。
  • @CharuAwhad:在执行任何 JavaScript 之前,使用 scrapy shell 测试 scrapy 在加载页面时看到的内容。从那里测试您的 XPath 表达式。更多信息:doc.scrapy.org/en/latest/topics/shell.html
  • 亲爱的劳伦斯,你有什么例子吗?因为我是初学者。所以没有得到正确........

标签: python ajax pagination scrapy


【解决方案1】:

我希望下面的代码会有所帮助。

somespider.py

​​>
# -*- coding: utf-8 -*-
import scrapy
import re
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.selector import Selector
from scrapy.spider import BaseSpider
from demo.items import DemoItem
from selenium import webdriver

def removeUnicodes(strData):
        if(strData):
            strData = strData.encode('utf-8').strip() 
            strData = re.sub(r'[\n\r\t]',r' ',strData.strip())
        return strData

class demoSpider(scrapy.Spider):
    name = "domainurls"
    allowed_domains = ["domain.com"]
    start_urls = ['http://www.domain.com/used/cars-in-trichy/']

    def __init__(self):
        self.driver = webdriver.Remote("http://127.0.0.1:4444/wd/hub", webdriver.DesiredCapabilities.HTMLUNITWITHJS)

    def parse(self, response):
        self.driver.get(response.url)
        self.driver.implicitly_wait(5)
        hxs = Selector(response)
        item = DemoItem()
        finalurls = []
        while True:
            next = self.driver.find_element_by_xpath('//div[@class="showMoreCars hide"]/a')

            try:
                next.click()
                # get the data and write it to scrapy items
                item['pageurl'] = response.url
                item['title'] =  removeUnicodes(hxs.xpath('.//h1[@class="page-heading"]/text()').extract()[0])
                urls = self.driver.find_elements_by_xpath('.//a[@id="linkToDetails"]')

                for url in urls:
                    url = url.get_attribute("href")
                    finalurls.append(removeUnicodes(url))          

                item['urls'] = finalurls

            except:
                break

        self.driver.close()
        return item

items.py

from scrapy.item import Item, Field

class DemoItem(Item):
    page = Field()
    urls = Field()
    pageurl = Field()
    title = Field()

注意: 您需要运行 selenium rc 服务器,因为 HTMLUNITWITHJS 仅使用 Python 与 selenium rc 一起使用。

运行你的 selenium rc 服务器发出命令

java -jar selenium-server-standalone-2.44.0.jar

使用命令运行你的蜘蛛

spider crawl domainurls -o someoutput.json

【讨论】:

    【解决方案2】:

    您可以使用浏览器查看请求是如何发出的。

    在幕后,当您单击“显示更多汽车”按钮后,您的浏览器将请求一个 JSON 数据来提供您的下一页。您可以利用这一事实直接处理 JSON 数据,而无需使用 Selenium 或 PhantomJS 等 JavaScript 引擎。

    在您的情况下,作为第一步,您应该模拟用户向下滚动由您的 start_url 参数和配置文件给出的页面,同时您的网络请求发现浏览器用来请求该 JSON 的端点。为了发现这个端点,浏览器的配置文件工具上有一个 XHR(XMLHttpRequest) 部分,就像在 Safari 中一样,您可以在其中导航用于请求数据的所有资源/端点。

    一旦你发现了这个端点,这是一项简单的任务:你将你刚刚发现的端点作为 start_url 提供给你的 Spider,然后根据你的处理和浏览 JSON 的内容,你可以发现它是否是要请求的下一页。

    P.S.:我为你看到了端点 url 是 http://www.carwale.com/webapi/classified/stockfilters/?city=194&kms=0-&year=0-&budget=0-&pn=2

    在这种情况下,我的浏览器请求了第二个页面,正如您在参数 pn 中看到的那样。在发送请求之前设置一些标头参数很重要。我注意到在您的情况下,标题是:

    接受文本/纯文本,/; q=0.01

    推荐人 http://www.carwale.com/used/cars-in-trichy/

    X-Requested-With XMLHttpRequest

    sourceid 1

    用户代理 Mozilla/5.0...

    【讨论】:

    • 感谢您帮助我。我尝试使用 selenium 并编写了代码:
    • 尊敬的所有感谢您的指导我尝试了您的解决方案,但仍然没有获得所有网址。然后我点击了这个链接stackoverflow.com/questions/17975471/…。我试图通过 selenium 来做,但仍然无法抓取所有网址。我已经在这里stackoverflow.com/questions/27525142/… 发布了我的查询。谁能帮帮我....
    • @CharuAwhad,让自己舒服点,伙计。我在最后一条评论中看到了你的帖子。我注意到您使用click() 函数模拟了用户的行为以获取下一页。我想这对你不起作用。其实我不是这个意思。实际上,除了附加请求标头之外,您需要以显式方式请求向您返回 JSON 数据的端点 url,然后您可以处理和迭代下一页。这意味着您需要模拟幕后发生的事情,而不是模拟用户点击。希望你在那里取得成功。
    猜你喜欢
    • 2017-03-19
    • 1970-01-01
    • 2022-10-24
    • 2015-02-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多