半Ajax数据获取——京东商城爬取

我们来了解一下京东的商品爬取。

爬取方式是selenium+chromedriver获取数据。

我们首先分析一下京东网站,比较神奇

一:构造链接

我们以手机为例

第一页:https://search.jd.com/Search?keyword=%E6%89%8B%E6%9C%BA&enc=utf-8&wq=%E6%89%8B%E6%9C%BA&pvid=3c3ab700b76e414ab54d46a872c52372

第二页:https://search.jd.com/Search?keyword=%E6%89%8B%E6%9C%BA&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=%E6%89%8B%E6%9C%BA&cid2=653&cid3=655&page=3&s=55&click=0

第三页:https://search.jd.com/Search?keyword=%E6%89%8B%E6%9C%BA&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=%E6%89%8B%E6%9C%BA&cid2=653&cid3=655&page=5&s=108&click=0

我们观察一下第二页和第三页可以发现,改变的参数是page和s,倒数第二和第三项,从page看,似乎只有奇数页,也就是1,3,5。

那么,s是什么?为什么page不是1,2,3递增而是1,3,5?其他参数会影响别的商品爬取吗?比如,我还要爬钱包,是不是报keyword改成钱包的编码就行了?如果行就好,如果不行怎么办?参数从哪拿?上面全部都是必要参数吗?

一一解答:s参数未知,但它是无用参数,page1,3,5递增是因为,加载出每一页的数据,后半部分是ajax请求的数据,该部分其实也是单独页,也就是偶数页。其他参数影响爬取其他商品,因此不可行。部分参数非必要,看看请求,我们就可以拿到必要参数。

 我们可以看见它发送了一个ajax的请求,page是2,也就是说,偶数页在奇数页下面,通过ajax获取。

其实,url的构造,只需要:

'https://search.jd.com/Search?keyword={}&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&page={}&click=0'

在第一ge{}传商品名,第二个{}传页数。

二:ajax数据获取:

ajax数据隐藏在原数据下面,而且参数也不完全相同,直接把参数的page改成偶数,也不一定可行(我没试过),所以这里使用了selenium+chromedriver的方法,下拉界面,加载出ajax数据,在获取page_source即可。

我们上一下代码:

from selenium import webdriver
from lxml import etree
import time
import pymysql
from pymongo import MongoClient

class JDspider():
    def __init__(self):
        self.driver_path = 'D:\pythontools\chromedriver.exe'
        self.driver = webdriver.Chrome(executable_path=self.driver_path)
        self.base_url = 'https://search.jd.com/Search?keyword={}&enc=utf-8&qrst=1' \
                        '&rt=1&stop=1&vt=2&page={}&click=0'
        #链接MySQL数据库
        self.db = pymysql.connect(host="localhost", user="root", password="123",
                             database="jd", port=3306)
        # 获取游标
        self.cursor = self.db.cursor()
        #链接mongodb
        self.client = MongoClient()
        self.mdb = self.client['jd']
        self.collection = self.mdb['jd_shop']

    #构造url
    #京东网页前半部分普通加载为奇数页,后半部分属于ajax加载为偶数页
    #构造奇数页url,模拟浏览器下拉,获取偶数页数据,共获取2页
    def stru_url(self):
        category_list = ['手机','奢侈品','电脑','书籍','无人机','乐器','钟表','数码影音','生活电器']
        for category in category_list:
            #偶数页通过下拉浏览器界面获取数据,过滤掉偶数
            for x in range(1,3):
                if x%2 == 0:
                    continue
                url = self.base_url.format(category,x)
                self.get_list_url(url,category)
                # print(url)
            #     break
            # break
                time.sleep(5)
            time.sleep(5)

    #获取商品详情链接的url
    def get_list_url(self,url,category):
        self.driver.get(url)
        # js语句。将浏览器界面下拉5000个单位,加载出ajax请求数据
        js = "var q=document.documentElement.scrollTop=5000"
        self.driver.execute_script(js)
        #等待数据载入
        time.sleep(5)
        resp = self.driver.page_source
        html = etree.HTML(resp)
        detail_urls = html.xpath('//ul[contains(@class,"gl-warp")]/li//div[@class="p-img"]/a/@href')
        for detail_url in detail_urls:
            if "https:" not in detail_url:
                detail_url = "https:" + detail_url
            else:
                continue
            print(detail_url)
            self.parse_detail(detail_url,category)
            time.sleep(3)

    #解析传入的url并做信息提取,将信息传给存储函数
    def parse_detail(self,url,category):
        shop = {}
        #获取分类
        category = category
        self.driver.get(url)
        #获取数据并解析
        resp = self.driver.page_source
        html = etree.HTML(resp)
        # print(category)
        #获取名字
        name = "".join(html.xpath("//div[@class='sku-name']//text()")).strip()
        # print(name)
        #获取简介
        detail = "".join(html.xpath("//div[@id='p-ad']/@title")).strip()
        # print(detail)
        #获取价格
        price = "".join(html.xpath("//span[@class='p-price']//text()")).strip()
        # print(price)
        #获取图片链接
        p_url = "".join(html.xpath("//img[@id='spec-img']/@src"))
        p_url = "https:" + p_url
        # print(p_url)
        shop['category'] = category
        shop['name'] = name
        shop['detail'] = detail
        shop['price'] = price
        shop['p_url'] = p_url
        self.save_sql(shop)
        self.save_mongo(shop)

    #接收要存储的数据,存储到sql数据库
    def save_sql(self,shop):
        sql = """
        insert into jd_shop(id,name,detail,category,p_url,user_id,price) value 
        (null,%s,%s,%s,%s,null,%s)
        """
        name = shop['name']
        detail = shop['detail']
        category = shop['category']
        p_url = shop['p_url']
        price = shop['price']
        try:
            self.cursor.execute(sql,(name,detail,category,p_url,price))
            self.db.commit()
            print("sql存储成功")
        except Exception as e:
            print("Error:",e.args)

    #接收数据存储到mongodb数据量
    def save_mongo(self,shop):
        if self.collection.insert(shop):
            print("mongo存储成功")

if __name__ == '__main__':
    jd = JDspider()
    jd.stru_url()
js = "var q=document.documentElement.scrollTop=5000"
self.driver.execute_script(js)

直接从列表页获取不到图片链接,只能进到详情页。

这个5000是自己试出来的,可以加载出ajax数据

商品名不需要编码,到链接自己会完成编码

存储到两个数据库,MySQL和MongoDB,同学需要。

MySQL:

部分数据,而且同学用于做自己的网站,不需要很多数据,所以量不大。

MongoDB:

完。。。。

最后,xpath获取数据强烈推荐xpath-helper,很好用,很直观。

链接:https://pan.baidu.com/s/10PGixiEPPfZQoioMw5oZKA

提取码:kmyz

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值