如何将Python scrapy用于myltiple URL' s

时间:2017-06-16 04:58:32

标签: scrapy python-3.5

我的问题类似于这篇文章:

How to use scrapy for Amazon.com links after "Next" Button?

我希望我的抓取工具遍历所有"下一步"链接。我搜索了很多,但大多数人都关注如何解析ULR或只是将所有网址放在初始网址列表中。

到目前为止,我可以访问第一页并解析下一页的链接。但我不知道如何使用相同的爬虫(蜘蛛)访问该页面。我尝试将新网址附加到我的网址列表中,它会附加(我检查了长度),但稍后它没有访问该链接。我不知道为什么......

请注意,在我的情况下,我只知道第一页的网址。只有在访问第一页后才能获得第二页的URL。同样的,第(i + 1)页的网址隐藏在第i页中。

在解析功能中,我可以解析并打印正确的下一页链接URL。我只是不知道如何访问它。

请帮帮我。谢谢!

import scrapy
from bs4 import BeautifulSoup


class RedditSpider(scrapy.Spider):
    name = "test2"
    allowed_domains = ["http://www.reddit.com"]
    urls = ["https://www.reddit.com/r/LifeProTips/search?q=timestamp%3A1427232122..1437773560&sort=new&restrict_sr=on&syntax=cloudsearch"]

    def start_requests(self):
        for url in self.urls:
            yield scrapy.Request(url, self.parse, meta={
                'splash': {
                'endpoint': 'render.html',
                'args': { 'wait': 0.5 }
                }
            })
`

    def parse(self, response):
        page = response.url[-10:]
        print(page)
        filename = 'reddit-%s.html' % page
        #parse html for next link
        soup = BeautifulSoup(response.body, 'html.parser')
        mydivs = soup.findAll("a", { "rel" : "nofollow next" })
        link = mydivs[0]['href']
        print(link)
        self.urls.append(link)

        with open(filename, 'wb') as f:
            f.write(response.body)

更新

感谢Kaushik的回答,我想出了如何让它发挥作用。虽然我仍然不知道为什么我最初想要添加新网址的想法不起作用...... 更新后的代码如下:

import scrapy
from bs4 import BeautifulSoup


class RedditSpider(scrapy.Spider):
    name = "test2"
    urls = ["https://www.reddit.com/r/LifeProTips/search?q=timestamp%3A1427232122..1437773560&sort=new&restrict_sr=on&syntax=cloudsearch"]

    def start_requests(self):
        for url in self.urls:
            yield scrapy.Request(url, self.parse, meta={
                'splash': {
                'endpoint': 'render.html',
                'args': { 'wait': 0.5 }
                }
            })


    def parse(self, response):
        page = response.url[-10:]
        print(page)
        filename = 'reddit-%s.html' % page
        with open(filename, 'wb') as f:
            f.write(response.body)

        #parse html for next link
        soup = BeautifulSoup(response.body, 'html.parser')
        mydivs = soup.findAll("a", { "rel" : "nofollow next" })
        if len(mydivs) != 0:
            link = mydivs[0]['href']
            print(link)  
            #yield response.follow(link, callback=self.parse)
            yield scrapy.Request(link, callback=self.parse)

1 个答案:

答案 0 :(得分:0)

Scrapy docs中对您的要求进行了详细解释。我不认为除此之外你还需要其他任何解释。建议进行一次以便更好地理解。

首先简要解释一下:

要关注指向下一页的链接,Scrapy提供了许多方法。最基本的方法是使用http.Request方法

  

Request object
  class scrapy.http.Request(url [,callback,   method =' GET',header,body,cookies,meta,encoding =' utf-8',   priority = 0,dont_filter = False,errback,flags])

>>> yield scrapy.Request(url, callback=self.next_parse)
  • url(string) - 此请求的网址
  • callback(callable) - 将使用此请求的响应(一旦下载)调用的函数作为其第一个参数。

为方便起见,Scrapy内置了使用response.follow创建Request对象的快捷方式,其中url可以是绝对路径或相对路径。

  

关注(网址,回调=无,方法=' GET',标头=无,正文=无,   cookies = None,meta = None,encoding = None,priority = 0,dont_filter = False,   errback可=无)

>>> yield response.follow(url, callback=self.next_parse)

如果您必须通过将值传递到表单或任何其他类型的输入字段来转到下一个链接,则可以使用{{3 }}。 Form Request objects扩展了基本请求功能  用于处理HTML表单。它使用lxml.html表单进行预填充  表单字段,包含来自Response对象的表单数据。

  

FormRequest class
  from_response(response [,formname = None,   formid = None,formnumber = 0,formdata = None,formxpath = None,   formcss = None,clickdata = None,dont_click = False,...])

如果您想在蜘蛛中模拟HTML表单 POST 并发送几个键值字段,您可以返回一个FormRequest对象(来自您的蜘蛛),如下所示:

return [FormRequest(url="http://www.example.com/post/action",
                    formdata={'name': 'John Doe', 'age': '27'},
                    callback=self.after_post)]
  

注意:如果请求未指定回调,则将使用spider的parse()方法。如果在处理期间引发异常,则会调用errback。