京东商城大规模爬虫

一开始看京东商城的商品,发现很多信息都在网页源代码上,以为会比淘宝的大规模爬取简单点,结果被京东欺骗了无数次,整整写了差不多六个小时,真是坑爹啊。先贴上github地址:https://github.com/xiaobeibei26/jingdong

先说下这个网站,首先在首页随便输入一个想爬取的商品类别,观察到一般商品数目都是100页的,除非有些比较稀少的商品,如图

Paste_Image.png

介绍一下网站的分析过程,默认情况下在首页输入一件商品时,出来的搜索页面是只有30件商品的,屏幕的右侧下拉框拉到下面会触发一个ajax的请求,把剩下的30个商品渲染出来,一般每页60个商品里面是有三个左右是广告的,也就是有效商品一般是57个。这里看一下这个AJAX请求,这个是爬取难点

Paste_Image.png

看一看这个请求头,我当时第一个感觉以为很多参数是可以去掉,拿到一个很简便的链接就可以了


当时没注意,删了很多参数直接请求,结果调试了很久,获得的商品在插进数据库去重的时候都是只剩网页的一般,细细观察了一下发现链接虽然不同,请求回来的商品却是一样的,然后我再细细看了看这个ajax请求,鼓捣了好久,最终发现这个URL后面的每个数字都是每一件商品的ID,而这个ID隐藏在第一次刚打开网页时候最初的那些商品里面,如图.........

Paste_Image.png

这里结合ajax请求的参数看,

Paste_Image.png

然后我又从新改掉爬虫逻辑,改代码,又花了两个小时,好惨啊.......

然后终于可以一次提取完整的网页商品了,最后提示一下,京东网页第一页的商品里面页数page是显示1和2的,第二页是3和4,这个有点特殊,最后上一张爬虫主程序图

# -*- coding: utf-8 -*-
import scrapy

from jingdong.items import JingdongItem

class JdSpider(scrapy.Spider):
    name = "jd"
    allowed_domains = ["www.jd.com"]
    start_urls = ['http://www.jd.com/']


    search_url1 = 'https://search.jd.com/Search?keyword={key}&enc=utf-8&page={page}'

    #search_url2='https://search.jd.com/s_new.php?keyword={key}&enc=utf-8&page={page}&scrolling=y&pos=30&show_items={goods_items}'

    search_url2= 'https://search.jd.com/s_new.php?keyword={key}&enc=utf-8&page={page}&s=26&scrolling=y&pos=30&tpl=3_L&show_items={goods_items}'
    shop_url ='http://mall.jd.com/index-{shop_id}.html'


    def start_requests(self):
        key = '裤子'
        for num in range(1,100):
            page1 = str(2*num-1)#构造页数
            page2 = str(2*num)
            yield scrapy.Request(url=self.search_url1.format(key=key,page=page1),callback=self.parse,dont_filter = True)
            yield scrapy.Request(url=self.search_url1.format(key=key,page=page1),callback=self.get_next_half,meta={'page2':page2,'key':key},dont_filter = True)
            #这里一定要加dont_filter = True,不然scrapy会自动忽略掉这个重复URL的访问

    def get_next_half(self,response):
        try:
            items = response.xpath('//*[@id="J_goodsList"]/ul/li/@data-pid').extract()
            key = response.meta['key']
            page2 =response.meta['page2']
            goods_items=','.join(items)
            yield scrapy.Request(url=self.search_url2.format(key=key, page=page2, goods_items=goods_items),
                                 callback=self.next_parse,dont_filter=True)#这里不加这个的话scrapy会报错dont_filter,官方是说跟allowed_domains冲突,可是第一个请求也是这个域名,实在无法理解

        except Exception as e:
            print('没有数据')



    def parse(self, response):
        all_goods = response.xpath('//div[@id="J_goodsList"]/ul/li')
        for one_good in all_goods:
            item = JingdongItem()
            try:
                data = one_good.xpath('div/div/a/em')
                item['title'] = data.xpath('string(.)').extract()[0]#提取出该标签所有文字内容
                item['comment_count'] = one_good.xpath('div/div[@class="p-commit"]/strong/a/text()').extract()[0]#评论数
                item['goods_url'] = 'http:'+one_good.xpath('div/div[4]/a/@href').extract()[0]#商品链接
                item['shops_id']=one_good.xpath('div/div[@class="p-shop"]/@data-shopid').extract()[0]#店铺ID
                item['shop_url'] =self.shop_url.format(shop_id=item['shops_id'])
                goods_id=one_good.xpath('div/div[2]/div/ul/li[1]/a/img/@data-sku').extract()[0]
                if goods_id:
                    item['goods_id'] =goods_id
                price=one_good.xpath('div/div[3]/strong/i/text()').extract()#价格
                if price:#有写商品评论数是0,价格也不再源代码里面,应该是暂时上首页的促销商品,每页有三四件,我们忽略掉
                    item['price'] =price[0]


                yield item
            except Exception as e:
                pass


    def next_parse(self,response):
        all_goods=response.xpath('/html/body/li')
        for one_good in all_goods:
            item = JingdongItem()
            try:
                data = one_good.xpath('div/div/a/em')
                item['title'] = data.xpath('string(.)').extract()[0]  # 提取出该标签所有文字内容
                item['comment_count'] = one_good.xpath('div/div[@class="p-commit"]/strong/a/text()').extract()[0]  # 评论数
                item['goods_url'] = 'http:' + one_good.xpath('div/div[4]/a/@href').extract()[0]  # 商品链接
                item['shops_id'] = one_good.xpath('div/div[@class="p-shop"]/@data-shopid').extract()[0]  # 店铺ID
                item['shop_url'] = self.shop_url.format(shop_id=item['shops_id'])
                goods_id = one_good.xpath('div/div[2]/div/ul/li[1]/a/img/@data-sku').extract()[0]
                if goods_id:
                    item['goods_id'] = goods_id
                price = one_good.xpath('div/div[3]/strong/i/text()').extract()  # 价格
                if price:  # 有写商品评论数是0,价格也不再源代码里面,应该是暂时上首页的促销商品,每页有三四件,我们忽略掉
                    item['price'] = price[0]

                yield item
            except Exception as e:
                pass

pipline代码如图

class JingdongPipeline(object):
    # def __init__(self):
    #     self.client = MongoClient()
    #     self.database = self.client['jingdong']
    #     self.db = self.database['jingdong_infomation']
    #
    # def process_item(self, item, spider):#这里以每个用户url_token为ID,有则更新,没有则插入
    #     self.db.update({'goods_id':item['goods_id']},dict(item),True)
    #     return item
    #
    # def close_spider(self,spider):
    #     self.client.close()






    def __init__(self):
        self.conn = pymysql.connect(host='127.0.0.1',port=3306,user ='root',passwd='root',db='jingdong',charset='utf8')
        self.cursor = self.conn.cursor()

    def process_item(self, item, spider):
        try:#有些标题会重复,所以添加异常
            title = item['title']
            comment_count = item['comment_count']  # 评论数
            shop_url = item['shop_url'] # 店铺链接
            price = item['price']
            goods_url = item['goods_url']
            shops_id = item['shops_id']
            goods_id =int(item['goods_id'])
            #sql = 'insert into jingdong_goods(title,comment_count,shop_url,price,goods_url,shops_id) VALUES (%(title)s,%(comment_count)s,%(shop_url)s,%(price)s,%(goods_url)s,%(shops_id)s,)'
            try:
                self.cursor.execute("insert into jingdong_goods(title,comment_count,shop_url,price,goods_url,shops_id,goods_id)values(%s,%s,%s,%s,%s,%s,%s)", (title,comment_count,shop_url,price,goods_url,shops_id,goods_id))

                self.conn.commit()
            except Exception as e:
                pass

        except Exception as e:
            pass

运行结果如图

Paste_Image.png

运行了几分钟,每页一千条,共爬了几万条裤子,京东的裤子真是多
mysql数据库插入操作

Paste_Image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容