三级页面爬取苏宁图书

接上篇文章https://blog.csdn.net/weixin_43094046/article/details/107930745
还是新创建一个项目suningDemo。其实可以在上次的项目中进行迭代这里为了以后方便查看就新建了个项目。
首先将上次的项目整个拷贝。
这次爬取的页面:https://book.suning.com/
爬取页面
页面结构:
页面结构

这里实现三级页面仅对三个文件suingDemoSpider,Middleware,items进行改动就可实现。
困难点:大小分类的对应。
项目结构:
项目结构
items加入三级页面所需要的注释

import scrapy


class SuningdemoItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    id = scrapy.Field()  # 出版时间
    bkName = scrapy.Field()  # 图书的名字
    price = scrapy.Field()  # 图书的价格
    commentNumber = scrapy.Field()  # 评价的人数
    bkShop = scrapy.Field()  # 所在的书店
    bkUrl = scrapy.Field()  # URL
    author = scrapy.Field()  # 作者
    press = scrapy.Field()  # 出版社
    publishTime = scrapy.Field()  # 出版时间
    bkType = scrapy.Field() #图书的类别
    bkHref = scrapy.Field() #类型的url
    bkTypes = scrapy.Field() #图书的小类别

suningDemoSpider

from copy import deepcopy

import scrapy


class SuningdemospiderSpider(scrapy.Spider):
    name = 'suningDemoSpider'
    allowed_domains = ['suning.com']
    start_urls = ['https://book.suning.com/']
    # start_urls = ['https://list.suning.com/1-502320-0.html']

    def parse(self, response):
        book_type = response.xpath('//div[@class="menu-item"]/dl/dt')
        item = {}
        for book in book_type:
            item['bkType'] = book.xpath('./h3/a/text()').extract_first()
            book_href = book.xpath('./following-sibling::* /a')#识别大小分类,进行循环输出
            for bk in book_href:
                item['bkTypes'] = bk.xpath('./text()').extract_first()
                item['bkHref'] = bk.xpath('./@href').extract_first()
                yield scrapy.Request(item["bkHref"], callback=self.parse_frist, meta={"item": deepcopy(item)})

    def parse_frist(self, response):#解析
        item = response.meta["item"]
        book_lists = response.xpath('//div[@id="filter-results"]/ul/li')
        print(len(book_lists))
        for book in book_lists:
            item['bkName'] = book.xpath('.//div[@class="res-info"]/p[2]/a/text()').extract_first()
            price1 = str(book.xpath('.//div[@class = "res-info"]/p[1]/em/text()').extract_first())
            price2 = str(book.xpath('//*[@id="filter-results"]/ul/li[1]/div/div/div/div[2]/p[1]/em/i[1]/text()').extract_first())
            item["price"] = price1 + price2
            item['commentNumber'] = book.xpath('.//div[@class="res-info"]/p[3]/a[1]/text()').extract_first()
            item['bkShop'] = book.xpath('.//div[@class="res-info"]/p[4]/a[1]/text()').extract_first()
            item['bkUrl'] = "https:" + book.xpath('.//div[@class="res-info"]/p[2]/a[1]/@href').extract_first()
            yield scrapy.Request(item["bkUrl"], callback=self.parse_detail, meta={"item": deepcopy(item)})

    def parse_detail(self, response):
        item = response.meta["item"]
        item["author"] = response.xpath('//li[@class="pb-item"][1]/text()').extract_first() if response.xpath('//li[@class="pb-item"][1]/text()').extract_first() is not None else "未知"
        item["press"] = response.xpath('//li[@class="pb-item"][2]/text()').extract_first() if response.xpath('//li[@class="pb-item"][2]/text()').extract_first() is not None else "未知"
        item["publishTime"] = response.xpath('//li[@class="pb-item"][3]/span[2]/text()').extract_first() if response.xpath('//li[@class="pb-item"][3]/span[2]/text()').extract_first() is not None else "未知"
        yield item
        print(item)

错误写法:

def parse(self, response):
        book_type = response.xpath('//div[@class="menu-item"]/dl/dt')
        book_href = resonse.xpath('//div[@class="menu-item"]/dl/dd')
        item = {}
        for book in book_type:
            item['bkType'] = book.xpath('./h3/a/text()').extract_first() 
            for bk in book_href:
                item['bkTypes'] = bk.xpath('./a/text()').extract_first()
                item['bkHref'] = bk.xpath('./a/@href').extract_first()
                yield scrapy.Request(item["bkHref"], callback=self.parse_frist, meta={"item": deepcopy(item)})

这样也能爬取数据但是循环的是整个的小标题,不管这个大标题下有没有都循环输出,导致大小分类出现错误,也就是数据不对应。开始我就天真的下来了,后面查看数据的时候发现少儿下居然有4级书就觉得这个数据不对应。所以就用了我上面的写法通过大类来循环小类。下面是我做大小分类测试时候,控制台输出很明显能看出来区别。期刊杂志和进口原版书的页面布局与其他的不一样这里就暂不做爬取。
正确截图:正确截图

错误截图:
错误截图

Middleware这里我只是稍微改动了下,爬取的是单页面的数据,分类下来也很多了。

class SeleniumDownloaderMiddleware:
    """
    构造方法
    """
    def __init__(self):
        self.browser = webdriver.Chrome(r'C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe')  # 每个spider初始化一次driver
    """
    动态网页处理中间件
    """
    def process_request(self, request, spider):#普通selenium的使用
        if spider.name == 'suningDemoSpider' and not (request.url.startswith("https://product")):
            # 根据特定Spider 决定是否利用selenium模拟浏览器爬取
            self.browser.get(request.url)  # selenium请求了网页 获得的Response 因此process_request不需要再返回Request给Downloader
            time.sleep(10)  # 延时10s 待网页完全加载后打印html文本
            print("访问:", request.url)
            print("current_url", self.browser.current_url)
            # urlchangecnt = 0
            # while (urlchangecnt < 3) :
            self.browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
            time.sleep(10)
            body = self.browser.page_source
            #     self.browser.find_element_by_id('nextPage').send_keys(Keys.ENTER)
            #     urlchangecnt = urlchangecnt + 1
            print("二级访问:", request.url)
            return HtmlResponse(self.browser.current_url, body=body,
                                encoding="utf-8", request=request)  # 这里必须返回Response的类或派生类
                                                            #只有这样Scrapy才不会返回Request给Downloader

----------------------------------------8.20更新-------------------------------------------------
早就更改了项目,一直没时间来更新。
上面的项目存在几个问题,爬取的速度慢,数据获取不完全和报错,这次针对这三个问题做了更改。其实之前这个项目也在报错但我没注意这也是其中导致数据量获取不完全的原因。
主要是在settings上做文章

# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False
LOG_LEVEL = 'WARNING'
LOG_FILE = 'log.txt'
CONCURRENT_REQUESTS = 1000
COOKIES_ENABLED = False
RETRY_ENABLED = False
CONCURRENT_REQUESTS_PER_DOMAIN = 10000
CONCURRENT_REQUESTS_PER_IP = 0
# DOWNLOAD_TIMEOUT = 20

报错1
报错2

首先说报错,由于我是在上次的项目上进行迭代的。则保留了timeout =3,就有些链接会超时,这样就得不全数据,我就调高了等待时间,也不行,后来查阅了一下更改了请求头将原来的http更改成https这样才好。剩下的仅仅是写微调这里就不做太多展示了。还写了一个爬取更多页面,分类更加的细致。这两者大同小异只是这个数据量更大,以至于跑一遍不想再跑第二遍。爬取页面部分截图见下图。等过段时间把项目都放在GitHub上吧。
更多数据

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值