京东的商品爬虫

来源:互联网 发布:淘宝卖家页面生成器 编辑:程序博客网 时间:2024/04/30 10:29


那么先看一下需求


获取某个关键词,例如‘土豆/水饺/裤子’

然后根据关键词获得所有有关于此类商品的信息

并在基础上进行简单的剔除无效信息的操作,

例如我想获取所有农产品土豆的信息,但是如果键入土豆无疑会获得类似削皮刀之类的东西


那么这时候我们就需要将他剔除,感谢京东,对物品的分类信息做的很细腻,我们可以直接获取到京东的商品信息,从而进行判断


但是例如搜索猪肉时。是会有许多种类的,此时我们就没法做到很好的剔除工作,如果有建议的朋友可以指导一下大笑


class new_Thread(threading.Thread):    def __init__(self,Dic):        threading.Thread.__init__(self)        self.Dic = Dic    def run(self):        self.result = getxinxi(self.Dic)    def get_result(self):        return self.result

先上一下线程的重定义,相对重量级的爬虫采取多线程的话效率会快上不好(不过对于现在手头这个2核的电脑。。可能效果不是特别好)


那么接下来开始对京东的搜索过程进行分析

以土豆作为关键字:

https://search.jd.com/Search?keyword=%E5%9C%9F%E8%B1%86&enc=utf-8&wq=&pvid=8591a7d46ea8404aba95e8f0613fa1de

经过尝试可以吧pvid给扔了

那https://search.jd.com/Search?keyword=%E5%9C%9F%E8%B1%86&enc=utf-8&wq=&

keyword显然是土豆,那么我们可以在这个网页获得什么呢?

url = 'https://search.jd.com/Search?keyword=%E5%9C%9F%E8%B1%86&enc=utf-8'content =requests.get(url).textselector = etree.HTML(content)links = selector.xpath(".//*[@id='J_goodsList']/ul/li/div/div[1]/a/@href")
以这个为例

我们获得了网页上商品的href属性,即链接

但是一页有60个商品,这里只有30条,很明显网页采取了动态加载。

此时我们开始抓包

https://search.jd.com/s_new.php?keyword=%E5%9C%9F%E8%B1%86&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&stock=1&page=2&s=31&scrolling=y&log_id=1501053622.70266&tpl=1_M&show_items=4181290,5187466,2902583,3742735,4019068,4342735,3876067,13521003503,13180188297,2329545,3382260,13461460252,1595871447,10272539167,10429929292,13239830319,3037821,12046382476,12160864074,12883026171,12325862734,13139706111,13324208094,12657657243,12065839723,10931189270,10723290126,14193195383,11829758955,11828453656

同样,这是url

根据头信息可以轻松获得 Referer

这个show_items又可以从上30条信息获取到,随后只要更换page的值即可

    urlbase = 'https://search.jd.com/s_new.php?keyword=%s&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=%s&stock=1&page=%d&s=28&scrolling=y&log_id=%s'    for i in range(1,40):        header = {            'Referer':'https://search.jd.com',        }        content = requests.get(urlbase%(Str,Str,i,getstr(Str)),headers=header).text

这里讲page keyword wq和log_id作为后续加入,方便更换关键字,具体实现在后面贴全部代码

这个接口中返回的数据是需要进行处理的,如何获得我们想要的信息呢?

首先确认一下有效信息:

商品的title 标题,href链接 以及价格price

在价格这边我没法在商品的网站找到任何信息,估计是没有的

        pat_sta = re.compile('<a target="_blank" title="(.*?)" href="(.*?)"')        items = re.findall(pat_sta,content)        for k in items:            if k[1] not in href and 'https' not in k[1]:                href.append(k[1])                id = k[1].replace(u'//item.jd.com/','')                Dic[key] = {}                Dic[key]['id'] = id.replace(u'.html','')                Dic[key]['href'] = k[1]                Dic[key]['title'] = k[0]                pat_price = re.compile('<strong class="J_%s" data-price="(\d+\.\d+)">'%Dic[key]['id'])                items = re.findall(pat_price,content)                if items!=[]:                    Dic[key]['price'] = items[0]


这一块用的是正则表达式

匹配到了这几个属性

id即为商品的id,是唯一的

接下来 就是具体的每个商品的信息了

这个很简单,因为属性都是暴露的


def getxinxi(Dic):    Dict = Dic.copy()    for i in Dic.keys():        time.sleep(1)        try:            content = requests.get('https:'+Dic[i]['href']).text            selector = etree.HTML(content)            #links = selector.xpath("body/div[8]/div[2]/div[1]/div[2]/div[1]/div[1]/ul[2]/li/text()")            links = selector.xpath(".//*[@id='detail']/div[2]/div[1]/div[1]/ul[2]/li/text()")            for link in links:                items_link = link.split(u':')                if items_link.__len__()==2:                    Dict[i][items_link[0]] = items_link[1]            links_dianpu = selector.xpath(".//*[@id='parameter-brand']/li/a/text()")            if links_dianpu!=[]:                Dict[i][u'店铺'] = links_dianpu[0]            header1 = {                'Referer': 'https://item.jd.com',            }            url = 'https://club.jd.com/comment/productCommentSummaries.action?referenceIds=%s'            content2 = requests.get(url%Dict[i]['id'],headers=header1).text            Str1 = json.loads(content2)            Dict[i][u'allcount'] = str(Str1[u'CommentsCount'][0][u'CommentCount'])+'+'            Dict[i][u'goodcount'] = str(Str1[u'CommentsCount'][0][u'GoodCount'])+'+'            Dict[i][u'genecount'] = str(Str1[u'CommentsCount'][0][u'GeneralCount'])+'+'            Dict[i][u'poorcount'] = str(Str1[u'CommentsCount'][0][u'PoorCount'])+'+'        except:            print 'Error'+Dic[i]['title']    return Dict

传递一个字典,这个字典即是上面获取到的字典

返回的字典是带有商品信息的

那么还有一个值得参考的部分就是商品的评论信息

也写在上面的代码里了,具体是如何获取的和第一步类似,直接抓到评论的url就行了

大家可以拿去跑了试一下

这是获取log_id的函数

def getstr(s):    html = requests.get('https://search.jd.com/Search?keyword=%s&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=%s'%(s,s)).text    soup = BeautifulSoup(html, 'lxml')    lis = soup.find_all("li", class_='gl-item')    str1 = ''    for li in lis:        data_pid = li.get("data-sku")        str1=str1+str(data_pid)+','    return str1
s是 土豆或者是别的的关键词


没用数据库我存在了excel里,给大家看一下效果图吧

最主要的几个实现代码都在上面了,其他就是如何多线程操作的,就不具体放上来了

谢谢~