Python爬虫实战--58同城二手商品爬虫

呜呜~~本来说今天就把代码上传上来,可惜了,还是有点差错,今天估计赶不上啦!明天加油吧!
今天我们一起来好好分析一下,看看我们该如何去爬去58二手商品。
这里我们分成四步来完成本次任务~
目标站点分析
目标URL:http://bj.58.com/sale.shtml
第一步:主页分析
在这里插入图片描述
在主页里面,我们需要提取说有的二级分类,特别注意,绿色框的内容,它的格式和内容,如其他的内容相差较大,所以我们一开始就把它剔除,从而在一定程度上减轻代码量和工作内容。

 # 解析main_url = "http://bj.58.com/sale.shtml" 获取分类URL
    def parse_index(self):
        category_urls = []
        html = self.parse_url(self.main_url)
        soup = BeautifulSoup(html.text, 'lxml')
        links = soup.select("ul.ym-submnu > li > b > a")
        for link in links:
            link_url = urljoin(self.main_url, link.attrs['href'])
            category_urls.append(link_url)
        self.DB.insert(collection='Category_urls', item=category_urls)

第二步:提取详情页链接
在这里插入图片描述
观察列表页,我们发现,有一些的详情页中不存在‘价格’,所以我们可以在提取详情页链接的时候直接将其筛选出来,这样我们在数据分析的时候就可以少做一点事了。

 # 解析分类链接并提取获取商品详情URL
    def parse_page_url(self):
        items = self.DB.find_data(collection='Category_urls')
        for item in items:
            cate_urls = item['category_urls']
            for cate_url in cate_urls:
                page_urls = []
                self.proxy = self.get_proxy()
                if 'tongxunyw' in cate_url:
                    print("error", cate_url)
                    pass
                elif 'ershouqiugou' in cate_url:
                    print("error", cate_url)
                    pass
                else:
                    print(cate_url)
                    for i in range(1, 100):
                        print("Parse page ", i)
                        url = cate_url + 'pn{}/'.format(i)
                        html = self.parse_url(url)
                        soup = BeautifulSoup(html.text, 'lxml')
                        trs = soup.select("tr[_pos='0']")
                        for tr in trs:
                            price = tr.select("b.pri")[0].get_text()
                            if price != '面议':
                                temp_link = tr.select("td.t > a:nth-of-type(1)")[0].attrs['href']
                                page_url = urljoin(self.main_url, temp_link)
                                page_urls.append(page_url)
                    item = dict(
                        page_urls=page_urls,
                    )
                    self.DB.insert(collection='Page_urls', items=item)

第三步:提取详情页数据
由于该详情页大致分为三种,所以必须采用三种模式去提取数据,如图
在这里插入图片描述
一眼看上去都差不多,但实际上里面的内容却有着很大的差别,比如说来之转转的内容,你不能直接冲网页里提取,而是的痛过转转API,获取json数据,在提取!笔者在编码时,也是调试了很多次才发现,原来这里有三种页面。醉了!没有办法,只好硬着头皮,写下去~

   # 解析Old58_urls网页,pp
    def parse_page_58(self, page_url):
        html = self.parse_url(page_url)
        soup = BeautifulSoup(html.text, 'lxml')
        temp_title = soup.title.get_text()
        title = temp_title.split(" - ")[0]
        try:
            temp_time = soup.select("div.detail-title__info > div")[0].get_text()
            time = temp_time.split(" ")[0]
            temp_price = soup.select("span.infocard__container__item__main__text--price")[0].get_text()
            price = temp_price.split()[0]
            temp = soup.select("div.infocard__container > div:nth-of-type(2) > div:nth-of-type(2)")[0].get_text()
            if '成新' in temp:
                color = temp
                temp_area = soup.select("div.infocard__container > div:nth-of-type(3) > div:nth-of-type(2)")[0]
            else:
                color = None
                temp_area = soup.select("div.infocard__container > div:nth-of-type(2) > div:nth-of-type(2)")[0]
            temp_area = list(temp_area.stripped_strings)
            area = list(filter(lambda x: x.replace("-", ''), temp_area))
            temp_cate = list(soup.select("div.nav")[0].stripped_strings)
            cate = list(filter(lambda x: x.replace(">", ''), temp_cate))
            item = dict(
                title=title,
                time=time,
                price=price,
                color=color,
                area=area,
                cate=cate,
                )
            print(item)
            self.DB.insert(collection='Page_data', items=item)
        except:
            print("Error 404!")

    # 解析New58_urls网页,并提取数据
    def parse_page_now58(self, page_url):
        html = self.parse_url(page_url)
        soup = BeautifulSoup(html.text, 'lxml')
        try:
            title = soup.select("div.detail-info-tit")[0].get_text()
            temp_cate = soup.select("div.nav")[0]
            temp_cate = list(temp_cate.stripped_strings)
            cate = list(filter(lambda x: x.replace(">", ''), temp_cate))
            ul = soup.select("ul.detail-info-bd")[0]
            time = ul.select("li:nth-of-type(1) > span:nth-of-type(2)")[0].get_text()
            color = ul.select("li:nth-of-type(2) > span:nth-of-type(2)")[0].get_text()
            area = ul.select("li:nth-of-type(3) > span:nth-of-type(2)")[0].get_text()
            temp_price = soup.select("span.info-price-money")[0].get_text()
            price = temp_price.split("¥")[-1]
            item = dict(
                title=title,
                time=time,
                price=price,
                color=color,
                area=area,
                cate=cate,
            )
            print(item)
            self.DB.insert(collection='Page_data', items=item)
        except:
            print("Error 404!")

    # 解析来自ZZ58_urls网页,并提取json数据
    def parse_page_zz(self, page_url):
        pattern = re.compile('infoId=(.*?)&', re.S)
        infoId = re.findall(pattern, page_url)
        html = self.parse_url(self.temp_api.format(infoId[0]))
        try:
            data_json = html.json()
            data = data_json.get('respData')
            local = data.get("location")
            item = dict(
                title=data.get('title'),
                browse_times=data.get("browseCount"),
                price=data.get("nowPrice"),
                origin_price=data.get("oriPrice"),
                area=local.get("local"),
            )
            print(item)
            self.DB.insert(collection='Page_data', items=item)
        except:
            print("Error 404!")

第四步:爬虫逻辑
由于整个的爬去量有点大,内容也相当的多,所以,我把数据都存储到了MongoDB里面,方便后续的使用,在爬虫时,也采用多进程分步的方式去爬去内容。减轻服务器的承担量~

# 逻辑实现
    def run(self):
        if INDEX_ENABLED:
            Index_process = Process(target=self.parse_index)
            Index_process.start()

        if LINK_ENABLED:
            PageUrl_process = Process(target=self.parse_page_url)
            PageUrl_process.start()

        if ITEM_ENABLED:
            Page_process = Process(target=self.parse_page)
            Page_process.start()

好了,今天的爬虫,就先讲到这里啦,代码里还有一些问题,明天调试好了,上传上来~
源码地址:https://github.com/NO1117/Sale58_Spider
Python交流群:942913325 欢迎大家一起交流学习
Question:如何进一步提高爬虫效率?大家可以考虑一下多线程多进程的方式~实现的可以找我聊聊哈

猜你喜欢

转载自blog.csdn.net/m0_37903789/article/details/84310790