繁体   English   中英

Scrapy 在认证后抓取每个链接

[英]Scrapy crawl every link after authentication

介绍

由于我的爬虫或多或少已经完成,我需要重做一个爬虫,它只爬取整个域的链接,我的工作需要这个。 抓取每个链接的蜘蛛应该每月运行一次。

我正在运行scrapy 2.4.0,我的操作系统是Linux Ubuntu server 18.04 lts

问题

我要抓取的网站更改了他们的“隐私”,因此您必须先登录才能看到产品,这就是我的“链接爬虫”不再起作用的原因。 我已经设法登录并抓取了我所有的东西,但是 start_urls 在 csv 文件中给出。

代码

import scrapy
from ..items import DuifItem
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from scrapy.http import FormRequest, Request
from scrapy_splash import SplashRequest

class DuifLinkSpider(CrawlSpider):
    name = 'duiflink'
    allowed_domains = ['duif.nl']
    login_page = 'https://www.duif.nl/login'
    start_urls = ['https://www.duif.nl']
    custom_settings = {'FEED_EXPORT_FIELDS' : ['Link']}
    
    def start_requests(self):
        yield SplashRequest(
        url=self.login_page,
        callback=self.parse_login,
        args={'wait': 3},
        dont_filter=True    
        )
    
    rules = (
       Rule(LinkExtractor(deny='https://www.duif.nl/nl/'), callback='parse_login', follow=True), 
    )
   
    def parse_login(self, response):
        return FormRequest.from_response(
            response,
            formid='login-form',
            formdata={
                'username' : 'not real',
                'password' : 'login data'},
            clickdata={'type' : 'submit'}, 
            callback=self.after_login)
        
    def after_login(self, response):
        accview = response.xpath('//ul[@class="nav navbar-nav navbar-secondary navbar-right"]//a/@href')[13]
        if accview:
            print('success')
        else:
            print(':(')
            
        for url in self.start_urls:
            yield response.follow(url=url, callback=self.search_links)
            
    def search_links(self, response):
        link = response.xpath('//ul[@class="nav navbar-nav navbar-secondary navbar-right"]/li/a/@href').get()
        
        for a in link:
            link = response.url
            yield response.follow(url=link, callback=self.parse_page)
                   

    def parse_page(self, response):
        productpage = response.xpath('//div[@class="product-details col-md-12"]')
        
        if not productpage:
            print('No productlink', response.url)
            
        for a in productpage:
            items = DuifItem()
            items['Link'] = response.url
            yield items

不幸的是,我无法提供一个虚拟帐户,您可以在其中尝试自己登录,因为它是一个 b2b 服务网站。

我可以想象我的“def search_links”是错误的。

我的计划结构是:

  1. 访问 login_page,传递我的登录凭据
  2. 检查是否通过 xpath 登录,在那里检查是否给出了注销按钮。
  3. 如果登录,它会打印“成功”
  4. 由 xpath 表达式给出,它应该开始遵循以下链接: html结构
  5. 通过访问每个链接,它应该通过 xpath xpression 检查是否给出了特定的容器,因此它知道它是否是产品页面。
  6. 如果是产品页面,则保存访问过的链接,如果不是产品页面,则使用下一个链接

控制台输出

控制台第 1 部分

控制台第 2 部分

如您所见,身份验证正在工作,但之后不会执行任何操作。

更新

我重新编写了我的代码:

import scrapy
from ..items import DuifItem
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from scrapy.http import FormRequest, Request
from scrapy_splash import SplashRequest

class DuifLinkSpider(CrawlSpider):
    name = 'duiflink'
    allowed_domains = ['duif.nl']
    login_page = 'https://www.duif.nl/login'
    start_urls = ['https://www.duif.nl/']
    custom_settings = {'FEED_EXPORT_FIELDS' : ['Link']}
    
    def start_requests(self):
        yield SplashRequest(
        url=self.login_page,
        callback=self.parse_login,
        args={'wait': 3},
        dont_filter=True    
        )
    
    rules = (
       Rule(LinkExtractor(), callback='parse_login', follow=True), 
    )
   
    def parse_login(self, response):
        return FormRequest.from_response(
            response,
            formid='login-form',
            formdata={
                'username' : 'not real',
                'password' : 'login data'},
            clickdata={'type' : 'submit'}, 
            callback=self.after_login)
        
    def after_login(self, response):
        accview = response.xpath('//ul[@class="nav navbar-nav navbar-secondary navbar-right"]//a/@href')[13]
        if accview:
            print('success')
        else:
            print(':(')
            
        for url in self.start_urls:
            yield response.follow(url=url, callback=self.search_links, dont_filter=True)
            
    def search_links(self, response):
        # link = response.xpath('//ul[@class="nav navbar-nav navbar-secondary navbar-right"]/li/a/@href')
        link = response.xpath('//a/@href')
        
        for a in link:
            link = a.get()
            link = 'https://www.duif.nl' + link if link else link
            yield response.follow(url=link, callback=self.parse_page, dont_filter=True)

    def parse_page(self, response):
        productpage = response.xpath('//div[@class="product-details col-md-12"]')
        
        if not productpage:
            print('No productlink', response.url)
            
        for a in productpage:
            items = DuifItem()
            items['Link'] = response.url
            yield items

现在我知道,我确实登录了,但它没有遵循“子”链接,但我想如果我使用response.xpath('//a/@href') ,它会自动搜索整个 dom每个链接。

在我的新控制台输出下方

控制台3

登录后,您将返回解析起始 url。 默认情况下,Scrapy 会过滤掉重复的请求,因此在您的情况下,它会在此处停止。 您可以通过在请求中使用 'dont_filter=True' 来避免这种情况,如下所示:

yield response.follow(url=url, callback=self.search_links, dont_filter=True)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM