• scrapy爬虫--苏宁图书


    实现业务逻辑如下:

    1. 创建scrapy项目,并生成 爬虫
    2. 在suning.py中实现Schedul 和 Spider业务逻辑
    3. 修改start_urls为正确的初始请求地址
    4. 构造parse(self,response)函数(底部封装自动发送请求,)获取响应
    5. 根据响应,使用xpath提取大分类和中间分类的list
    6. 根据上述得到的list再遍历,使用xpath提取我们需要的内容字段,存入刚构建的空dict中
    7. 如果要进入到下一个商品列表页面,则 yield 一个Requset对象,指明要进入的url,callback,以及把item通过meta传到列表页响应中。
    8. 构建callback对应的商品列表页面数据提取函数 parse_book_list(self,response),使用xpath提取我们需要的内容字段,使用yield response.yellow()构造请求,指明要进入的url(使用的是follow,所以可以是不完整的url),callback,以及把item通过meta传到详情页响应中。
    9. 构建callback对应的商品详情页面数据提取函数 parse_book_detail(self,response),使用xpath提取我们需要的内容字段,字段提取完成后,就可以把item返回了,yield item。
    10. 构建分类页中的后一部分图书列表数据请求,首先找到next_url,然后构造Request。
    11. 上述最终yield 的item 通过在settings中设置spiderpiplelines,就会进入指定的spiderpiplelines中通过process_item()进行进一步数据处理,比如清洗和保存。
    12. 另外在Downloader Middlewares中还可以设置open_spider(),close_spider(),做相应处理。
    # 注意点,scrapy框架底层实现了多线程,所以item传递时,为避免数据覆盖错位情况,需要使用deepcopy()传递下去。

    下面直接上代码:

    # suning.py
    # -*- coding: utf-8 -*-
    import scrapy
    import re
    from copy import deepcopy
    
    class SuningSpider(scrapy.Spider):
        name = 'suning'
        allowed_domains = ['suning.com']
        start_urls = ['https://book.suning.com/']
    
        def parse(self, response):
            #获取大分类的分组
            div_list = response.xpath("//div[@class='menu-list']/div[@class='menu-item']")
            # 和大分类呼应的中间分类组
            div_sub_list = response.xpath("//div[@class='menu-list']/div[@class='menu-sub']")
            for div in div_list[:1]:
                item = {}
                #大分类的名字--eg:文学艺术
                item["b_cate"] = div.xpath(".//h3/a/text()").extract_first()
                #当前大分类的所有的中间分类的位置
                current_sub_div = div_sub_list[div_list.index(div)]
                #获取中间分类的分组--eg: 小说,青春文学
                p_list = current_sub_div.xpath(".//div[@class='submenu-left']/p[@class='submenu-item']")
                for p in p_list:
                    #中间分类的名字
                    item["m_cate"] = p.xpath("./a/text()").extract_first()
                    #获取小分类的分组
                    li_list = p.xpath("./following-sibling::ul[1]/li")
                    for li in li_list:
                        #小分类的名字
                        item["s_cate"] = li.xpath("./a/text()").extract_first()
                        #小分类的URL地址
                        item["s_href"] = li.xpath("./a/@href").extract_first()
    
                        #请求图书的列表页
                        yield scrapy.Request(
                            item["s_href"],
                            callback=self.parse_book_list,
                            meta={"item":deepcopy(item)}
                        )
    
                        #发送请求,获取列表页第一页后一部分的数据
                        next_part_url_temp = "https://list.suning.com/emall/showProductList.do?ci={}&pg=03&cp=0&il=0&iy=0&adNumber=0&n=1&ch=4&sesab=ABBAAA&id=IDENTIFYING&cc=010&paging=1&sub=0"
                        #获取url地址的ci
                        ci = item["s_href"].split("-")[1]
                        next_part_url = next_part_url_temp.format(ci)
                        yield scrapy.Request(
                            next_part_url,
                            callback=self.parse_book_list,
                            meta={"item":deepcopy(item)}
                        )
    
        def parse_book_list(self,response): #处理图书列表页内容
            item = response.meta["item"]
            #获取图书列表页的分组
            # li_list = response.xpath("//div[@id='filter-results']/ul/li")
            li_list =response.xpath("//li[contains(@class,'product      book')]")
            for li in li_list[:1]:
                #书名
                item["book_name"] = li.xpath(".//p[@class='sell-point']/a/text()").extract_first().strip()
                #书的url地址,不完整
                item["book_href"] = li.xpath(".//p[@class='sell-point']/a/@href").extract_first()
                #书店名
                item["book_store_name"] = li.xpath(".//p[contains(@class,'seller oh no-more')]/a/text()").extract_first()
                #发送详情页的请求
                yield response.follow(
                    item["book_href"],
                    callback = self.parse_book_detail,
                    meta = {"item":deepcopy(item)}
                )
    
            #列表页翻页
            #前半部分数据的url地址
            next_url_1 = "https://list.suning.com/emall/showProductList.do?ci={}&pg=03&cp={}&il=0&iy=0&adNumber=0&n=1&ch=4&sesab=ABBAAA&id=IDENTIFYING&cc=010"
            #后半部分数据的url地址
            next_url_2 = "https://list.suning.com/emall/showProductList.do?ci={}&pg=03&cp={}&il=0&iy=0&adNumber=0&n=1&ch=4&sesab=ABBAAA&id=IDENTIFYING&cc=010&paging=1&sub=0"
            ci = item["s_href"].split("-")[1]
            #当前的页码数
            current_page = re.findall('param.currentPage = "(.*?)";',response.body.decode())[0]
            #总的页码数
            total_page = re.findall('param.pageNumbers = "(.*?)";',response.body.decode())[0]
            if int(current_page)<int(total_page):
                next_page_num = int(current_page) + 1
                next_url_1 = next_url_1.format(ci,next_page_num)  #组装前半部分URL
                yield scrapy.Request(
                    next_url_1,
                    callback=self.parse_book_list,
                    meta = {"item":item}
                )
                #构造后半部分数据的请求
                next_url_2 = next_url_2.format(ci,next_page_num)
                yield scrapy.Request(
                    next_url_2,
                    callback=self.parse_book_list,
                    meta = {"item":item}
                )
    
        def parse_book_detail(self,response):#处理图书详情页内容
            item = response.meta["item"]
            price_temp_url = "https://pas.suning.com/nspcsale_0_000000000{}_000000000{}_{}_10_010_0100101_226503_1000000_9017_10106____{}_{}.html"
            p1 = response.url.split("/")[-1].split(".")[0]
            p3 = response.url.split("/")[-2]
            p4 = re.findall('"catenIds":"(.*?)",',response.body.decode())
            if len(p4)>0:
                p4 = p4[0]
                p5 = re.findall('"weight":"(.*?)",',response.body.decode())[0]
                price_url = price_temp_url.format(p1,p1,p3,p4,p5)
                yield scrapy.Request(
                    price_url,
                    callback=self.parse_book_pirce,
                    meta={"item":item}
                )
    
        def parse_book_pirce(self,response): #提取图书的价格
            item = response.meta["item"]
            # item["book_price"] = re.findall('"netPrice":"(.*?)"',response.body.decode())[0]
            # print(item)
            yield item

    关于setting.py & pipeline.py & middlewares.py的代码比较简单,这里就不传了。

    <人追求理想之时,便是坠入孤独之际.> By 史泰龙
  • 相关阅读:
    网络安全笔记1-局域网、DOS、用户与组、远程、NTFS、文件共享、DHCP、DNS、WEB、FTP、域、PKI、扫描与爆破
    ASM入网小助手卸载
    列表拖拽排序 ----vue.js
    如何让谷歌索引你的页面
    命令导入大数据库

    大数据-快读
    微服务参考文章
    Java-BigDecimal踩坑记录
    CF1285F Classical?
  • 原文地址:https://www.cnblogs.com/jason-Gan/p/10609990.html
Copyright © 2020-2023  润新知