身份验证后,抓取抓取每个链接

时间:2020-10-21 07:43:10

标签: python python-3.x xpath scrapy web-crawler

简介

由于我的抓取工具或多或少已经完成,因此我需要重做一个仅对整个域抓取链接的抓取工具,因此我的工作需要这样做。 搜寻每个链接的爬虫应该每月运行一次。

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

问题

我必须爬网的网站更改了它们的“隐私”,因此必须先登录才能看到产品,这就是我的“ linkcrawler”不再起作用的原因。 我已经设法登录并抓取了我所有的东西,但是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-structure
  5. 通过访问每个链接,应该通过xpath xpression检查(是否提供了特定的容器),以便知道其是否为产品页面。
  6. 如果是产品页面,则保存访问过的链接;如果不是产品页面,则保存下一个链接

控制台输出

console part1

console part2

就像您看到的那样,身份验证正在运行,但是之后将不会执行任何操作。

更新

我对代码做了很多修改:

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

现在我知道,我确实已经登录,但是它没有遵循“ sub”链接,但是我认为如果我使用response.xpath('//a/@href'),它将自动在整个dom中搜索每个链接。

在我的新控制台输出下面

console3

1 个答案:

答案 0 :(得分:1)

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

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