美文网首页
Python爬虫之爬取商品信息

Python爬虫之爬取商品信息

作者: bohei111 | 来源:发表于2016-06-19 17:25 被阅读830次

    需求

    • 爬取若干页上的商品
    • 不包含推广商品和转转商品
    • 获取相应商品的详细信息,例如:标题、发布时间、成色、价格、区域、浏览量等

    开发环境

    Win7 64bit、Python3.5

    代码

    # -*- coding: utf-8 -*-
    from bs4 import BeautifulSoup
    import requests
    import time
    
    agent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
    cookie = 'f=n; f=n; id58=c5/ns1dl9yy83HPfDdvGAg==; ipcity=zz%7C%u90D1%u5DDE%7C0; als=0; __utma=253535702.38279276.1466300209.1466300209.1466300209.1; __utmc=253535702; __utmz=253535702.1466300209.1.1.utmcsr=zz.58.com|utmccn=(referral)|utmcmd=referral|utmcct=/; bj=201661993651; bj58_id58s="WEVVdFlpeD1VM3hkNjQ3MQ=="; sessionid=e2fa9381-317b-4e3f-9e1c-fd3705f6c894; myfeet_tooltip=end; 58home=bj; __track_id=20160619093746385471429630431203178; Hm_lvt_4d4cdf6bc3c5cb0d6306c928369fe42f=1466300268; Hm_lpvt_4d4cdf6bc3c5cb0d6306c928369fe42f=1466300268; city=bj; bdshare_firstime=1466300280136; bangbigtip2=1; f=n; final_history=26224745105338%2C25245379987755%2C26394563690054%2C26399654836521%2C26010296256313; bj58_new_session=0; bj58_init_refer=""; bj58_new_uv=3; 58tj_uuid=1b067d6e-d9f3-4b82-818b-3cdd2263501c; new_session=0; new_uv=3; utm_source=; spm=; init_refer='
    referer = 'http://bj.58.com/pbdnipad/0/?PGTID=0d3065d1-0000-114f-c494-6fa3a1961632&ClickID=1'
    headers = {'User-Agent':agent,'Cookie':cookie,'Referer':referer}
    
    # 获取页面上除了推广和转转外,所有商品的链接,将链接存储在list中返回。函数有两个参数,end_page参数,
    # 表示要获取商品的页数,sale参数默认为0,表示要获取个人商品,若要获取商家商品时,将sale置为1。
    def get_links_from_page(end_page,sale=0):
        links= []
        for page in range(1,end_page+1):
            url = 'http://bj.58.com/pbdn/{}/pn{}/'.format(sale,page)
            r = requests.get(url, headers=headers)
            if r.status_code != 200:
                continue
            time.sleep(4)
            soup = BeautifulSoup(r.text, 'lxml')
            for tr in soup.select('#infolist > table.tbimg'):                #避开了推广商品
                for item in tr.find_all('tr', class_=''):                         #避开了转转商品,注意class_的写法
                    links.append(item.select('td.t > a.t')[0].get('href'))
        # print(links)
        return links
    
    
    # 获取某一个商品的浏览量,浏览量是js控制的,直接抓取标签会返回0,在headers中药加入referer
    def get_views(url):
        id = url.split('?')[0].split('/')[-1].strip('x.shtml')
        infoid = 'http://jst1.58.com/counter?infoid={}'.format(id)
        r = requests.get(infoid,headers=headers)
        views = r.text.split('=')[-1]
        return views
    
    # 获取商品的信息
    def get_info(end_page,sale=0):
        urls = get_links_from_page(end_page,sale=0)
        for url in urls:
            r = requests.get(url, headers = headers)
            if r.status_code != 200:
                continue
            time.sleep(2)
            soup = BeautifulSoup(r.text, 'lxml')
            cate = soup.select('span > a[href="http://bj.58.com/pbdn/"]')
            title = soup.select('div > h1')
            date = soup.select('li.time')
            price = soup.select('span.price')
            state = soup.find_all('div', 'su_con')
            region = soup.select('.c_25d')
    
            data = {
                'category':cate[0].get_text(),
                'title':title[0].get_text(),
                'date':date[0].get_text(),
                'price':price[0].get_text(),
                'state':list(state[1].stripped_strings)[0],
                'region':''.join(list(region[0].stripped_strings)) if len(region)!=0 else '-',
                'seller':'个人' if sale == 0 else '商家',
                'views': get_views(r.url),   #重定向链接
            }
            print(data)
    
    # 爬取前两页的信息
    get_info(2)
    

    运行结果

    遇到的问题和解决方案

    1. 获取浏览量时,Chrome一直显示浏览量为0,即使刷新后也没有变化,在Sources中也没有发现任何URL返回浏览量信息。折腾了一个晚上,发现是chrome中的adblock plus没关,关掉后一切正常了。

    2. 使用get_view()函数获取浏览量,最初只把相应的网站传入,结果发有一个商品的浏览量是0,后来发现该链接有重定向链接,使用r.url获取重定向后的链接即可。

    3. 选取网页元素时,使用CSS Selector复制路径即可,但是复制的路径不一定能用,如果出现nth-child(),要改为nth-of-type()。路径中的'>'两边要有空格,否则会报错。

    4. <tbody>标签导致无法正常选取标签
      在最初编程时,为了避免选中推广商品的标签,曾将路径设为#infolist > table.tbimg > tbody > tr > td.t > a.t(这样依然会选中转转商品),结果竟然返回[]。代码如下:

    # -*- coding: utf-8 -*-
    from bs4 import BeautifulSoup
    import requests
    
    url = 'http://bj.58.com/pbdn/0/'
    r = requests.get(url)
    soup = BeautifulSoup(r.text, 'lxml')
    tag = soup.select(#infolist > table.tbimg > tbody > tr > td.t > a.t)
    print(tag)
    
    #结果为[]
    

    原因和解决方案:
    虽然在Elements下存在tbody标签,但是网页源代码中并没有该标签,如果使用print(soup),发现结果中也没有tbody标签。在网页中,tbody位于table中,用来提高解析速度。将路径改为#infolist > table.tbimg > tr > td.t > a.t即可。

    总结

    1. 浏览量是JS控制的,不能通过选取标签的方式获取
    2. 标签的选取需要逐步尝试
    3. 为了避开网站的反爬机制,需要添加headers,设置爬取的时间间隔
    4. 路径的含义
      例如:#infolist > table.tbimg > tbody > tr a.t路径,table.tbimg指class=tbimg的table标签,#infolist指id=infolist的标签,> 代表直接子标签,tr a.t之间的空格代表a是tr的间接子标签。

    相关文章

      网友评论

          本文标题:Python爬虫之爬取商品信息

          本文链接:https://www.haomeiwen.com/subject/hspbdttx.html