python爬虫构建自己的比价系统

前言

有一次在上课的时候看到jun19在浏览一个网站买东西(hhh),我大致看了一眼,该网站可以看到该件商品在不同商城的价格,我觉得有点意思,然后我就和他深入了解了一下该网站:(慢慢买),我就想要是爬下来,那就可以玩一下呀,然后我就找个时间写一下爬虫…

好了,不扯了…,直入主题吧~


实现前提:

如果你想实现的话:

  • 一定的网页基础
  • 网站抓包
  • python基础
  • 了解python爬虫框架scrapy

步骤01:分析网页

主要的详情说明已在图片上做了说明:


步骤02:分析网页url以及response

  • url:http://s.manmanbuy.com/Default.aspx?key=%C6%BB%B9%FB8&btnSearch=%CB%D1%CB%F7
    首先经验告诉我们,这个url是经过url编码的,所以我们通过url 解码之后的真实url应该是
    url_real:http://s.manmanbuy.com/Default.aspx?key=苹果8&btnSearch=搜索

    看着很亲切的参数出来了"苹果8",后面的参数可以省略…
    所以我们只需要通过改变url即可得到不同列表的数据了http://s.manmanbuy.com/Default.aspx?key=你想要的搜索的商品名称 ('你想要的搜索的商品名称’需要经过url gbk encode)

  • response:说白了就是字符串,也就是html
    通过查看源代码我们可以知道网页上的数据都在response中


步骤03:编写爬虫(scrapy.Spider)

  • 直接上代码如下:

      class TestSpider01(scrapy.Spider):
    
          def __init__(self):
              self.pipeline_utils = PipelineUtils()
              self.print_utils = PrintUtils()
              self.parse_utils = ParseUtils()
              self.redis_utils = RedisUtils()
              self.http_utils = HttpUtils()
              self.utils = Utils()
              dispatcher.connect(self.spider_closed, signals.spider_closed)
    
          def spider_closed(self, spider):
              self.print_utils.send_message(self.name, PrintUtils().print_end())  # 打印结束标志
    
          name = 'TestSpider01'
    
          custom_settings = {
              'DEFAULT_REQUEST_HEADERS': {
                  'Accept': "*/*",
                  'Accept-Language': "zh-CN,zh;q=0.8",
                  'Accept-Encoding': 'gzip, deflate',
                  'Connection': 'keep-alive',
                  'Referer': 'http://s.manmanbuy.com/',
                  'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',
                  'Upgrade-Insecure-Requests': '1',
              },
              'LOG_LEVEL': 'ERROR',
              # "COOKIES_ENABLED": True, # 开启COOKIES
          }
    
          start_url = 'http://s.manmanbuy.com/Default.aspx?key=苹果8'
          #            http://s.manmanbuy.com/Default.aspx?key=%C6%BB%B9%FB8&btnSearch=%CB%D1%CB%F7
    
          def start_requests(self):
              start_url = self.utils.url_encode(self.start_url, encoding='GBK')  # self.utils.url_encode() 封装的是 : parse.quote(text_str, encoding=encoding)
              yield scrapy.Request(url=start_url, callback=self.parse)
    
          def parse(self, response):
              # html_str = response.text
              # current_url = response.url
              print("+++>>" + response.url)
    
              select = scrapy.Selector(response)
              divs = select.xpath('//*[@id="listpro"]/div/div[@class="div1100"]/div')
              for one_div in divs:
                  goods_title =  ''.join(one_div.xpath('./div[@class="title"]/div[@class="t"]//*/text()').extract()).strip()
                  if not goods_title: continue # 如果标题为空,说明不是一个有效的div,跳过该div获取数据流程
    
                  data_dict = OrderedDict()
                  data_dict['商品标题'] = goods_title
    
                  # 这有一个问题就是 个别url是: '/productdetail.aspx?itemid=558550356564&skuid='
                  # 通过慢慢买官网我们可以知道实质链接是:'https://detail.tmall.com/item.htm?id=558550356564&sku_properties=10004:709990523;5919063:6536025;12304035:3222911'
                  # 有效的部分是 'https://detail.tmall.com/item.htm?id=558550356564',所以这里要做一个转换
                  goods_href = str(one_div.xpath('./div[@class="title"]/div[@class="t"]/a/@href').get().strip())
                  # self.utils.sub_str_between() 是我看了 Apache 中的 StringUtils 中的方法python化一个封装的方法而已
                  data_dict['商品链接'] = 'https://detail.tmall.com/item.htm?id=' + self.utils.sub_str_between(goods_href, 'itemid=', '&') if goods_href.startswith('/') else goods_href
    
                  data_dict['商品价格'] = ''.join(one_div.xpath('./div[@class="cost"]/div[@class="p AreaPrice"]//*/text()').extract()).strip()
                  data_dict['评论人数'] = one_div.xpath('./div[@class="comment"]/a/text()').get().strip()
                  data_dict['商城店铺'] = ''.join(one_div.xpath('./div[@class="mall"]').xpath('p[@class="m"]//*/text()|./p[@class="AreaZY"]/text()').extract()).strip()
                  data_dict['最新时间'] = one_div.xpath('./div[@class="mall"]/p[@class="t"]/text()').get().strip()
    
                  # 这里作数据持久化操作,这里作打印操作
                  print(data_dict['商品标题'], '\n', data_dict['商品链接'], '\n', data_dict['商品价格'], '\n', data_dict['评论人数'], '\n', data_dict['商城店铺'], '\n', data_dict['最新时间'], end='\n\n')
    
                  self.pipeline_utils.data_dict(self.name, "慢慢买商品对比价", data_dict, print_len_list=[10, 10, 10, 10, 10, 10])
    

步骤04:控制台输出

  • 我们可以看到已经成功抓取了~~


步骤05:持久化

  • 为了简练,代码我没贴出持久化代码,我这里做了持久化到excel文件中


步骤06:结束

  • 翻页

    最后我们就可以成功抓取到数据了,但是还没翻页,如需要翻页,可以观察一下url即可
    http://s.manmanbuy.com/Default.aspx?PageID=2&smallclass=0&ppid=0&siteid=&searchmode=0&f1=0&f2=0&f3=0&f4=0&f5=0&f6=0&price1=0&price2=0&orderby=score&iszy=0&istmall=0&zdj=0&key=%c6%bb%b9%fb8&v=&k=&min=&max=&w=&w2=&ft=&ft2=&distype=0,有效参数是:PageID and key

  • 声明

    在这里说明一下,数据来源于慢慢买,请不要商业用途,如果有侵权,请联系我删除,我怕警察叔叔.

  • 题外话

    就算不会写爬虫,慢慢买这个网站也为我们提供了很多便利,我们直接进该网站都可以满足很大一部分人的需求了…

  • 建议

    大家在玩的时候建议不要玩嗨了,控制好速度,不要猛的发起请求,理解一下运维 or 反爬虫工程师的工作~~

  • 后续

    我打算是有时间的话java化,到时候提供接口调用就方便了~ 如果有兴趣的话可以去看一下慢慢买APP,可以抓抓包,返回的是json数据,这里就不做介绍了~~


  • 讨论

    博客同步到 SHY BLOG
    如果你有更好的实现,联系我分享~~

    邮箱:272694308@qq.com

发布了42 篇原创文章 · 获赞 13 · 访问量 2万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 精致技术 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览