美文网首页Python数据采集与爬虫Python 爬虫专栏爬虫
从零开始学爬虫(2):突破限制,分类爬取,获得全部数据

从零开始学爬虫(2):突破限制,分类爬取,获得全部数据

作者: BruceYeen | 来源:发表于2017-02-16 15:23 被阅读829次

    这是我学习爬虫的笔记,作为备忘,如果可以帮到大家,那就更好了~
    从零开始学爬虫(1):爬取房天下二手房信息
    从零开始学爬虫(2):突破限制,分类爬取,获得全部数据
    从零开始学爬虫(3):通过MongoDB数据库获取爬虫数据

    上一篇爬取房天下二手房信息我们可以看到的信息有一个100页的限制,下面我们尝试通过分类爬取的方法获得全部数据。

    一、了解网站反爬限制

    以房天下二手房信息为例,不论选择哪一级分类标签,最高显示的页数上限都是100,如下图:

    图片.png
    图片.png

    想要突破这层限制,只需要把找房条件不断细化,直至符合条件的信息不足100页即可(如下图)。

    图片.png

    而每多一个筛选条件,URL就会发生一次变化,笔者试图从中发现一些规律,但没有成功,以下是按照城南不同区域的一些URL:

    城南:
    南稍门:http://esf.xian.fang.com/house-a0478-b04113/
    明德门:http://esf.xian.fang.com/house-a0478-b04122/
    三森:http://esf.xian.fang.com/house-a0478-b04125/
    陕师大:http://esf.xian.fang.com/house-a0478-b04126/
    文艺路:http://esf.xian.fang.com/house-a0478-b04130/
    小寨:http://esf.xian.fang.com/house-a0478-b04131/
    吉祥村:http://esf.xian.fang.com/house-a0478-b04635/
    省人民医院:http://esf.xian.fang.com/house-a0478-b04884/
    ……
    

    可以看到,这些URL并没有什么明显的规律,因此,我们先写一段小程序,把这些筛选条件对应的URL都爬下来,然后再按照这些URL去爬取每一页的信息。

    二、爬取筛选条件的URL

    先通过下面一段小程序把每一类筛选条件对应的URL爬下来:

    # -*- coding: utf-8 -*-
    
    from bs4 import BeautifulSoup
    import requests
    
    response = requests.get('http://esf.xian.fang.com/')
    soup = BeautifulSoup(response.text, 'lxml')
    
    regions = soup.select('#list_D02_10 > div.qxName > a')  # 区域
    totprices = soup.select('#list_D02_11 > p > a')  # 总价
    housetypes = soup.select('#list_D02_12 > a')  # 户型
    areas = soup.select('#list_D02_13 > p > a')  # 面积
    
    print('区域href:')
    n = 1
    while n < 11:
        print(regions[n].get('href'))
        n = n + 1
    print('总价href:')
    n = 1
    while n < 10:
        print(totprices[n].get('href'))
        n = n + 1
    print('户型href:')
    n = 1
    while n < 7:
        print(housetypes[n].get('href'))
        n = n + 1
    print('面积href:')
    n = 1
    while n < 10:
        print(areas[n].get('href'))
        n = n + 1
    

    结果如下:

    图片.png

    我们看到,如果单独抓取每一类标签的URL,每个前面都有一个house-或者house/,但是实际上多条件筛选的时候完整的URL是下图这样的,

    图片.png

    所以我们稍微变换一下代码,把这些按照实际的URL格式链接起来:

    n = 1
    while n < 11:
        m = 1
        while m < 10:
            i = 1
            while i < 7:
                j = 1
                while j < 10:
                    print('http://esf.xian.fang.com' + regions[n].get('href') + totprices[m].get('href')[7:-1] + '-' + housetypes[i].get('href')[7:-1] + '-' + areas[j].get('href')[7:])
                    j = j + 1
                i = i + 1
            m = m + 1
        n = n + 1
    

    这样一来,得到的结果就比较好了:

    图片.png

    OK,总共爬下来4860个URL,这么多的URL,想想就够了。。。即便按照我们爬下来URL库挨个进行访问和爬取的话,还存在一个问题:每一个URL下对应的页数具体是多少呢?我们总不能一个一个去点开看吧?而且,这些组合中有可能还存在超过100页的。怎么办呢?

    三、细化分类,确保每一类都少于100页

    我是这样做的,根据网页上的四种筛选条件,首先选择其中的两个条件组合(区域和户型),把它们的URL和对应的页数爬下来,

    # 按照区域和户型先分类看一下
    n = 1
    while n < 8:
        i = 1
        while i < 7:
            resp1 = requests.get('http://esf.xian.fang.com' + regions[n].get('href') + '-' + housetypes[i].get('href')[7:])
            soup1 = BeautifulSoup(resp1.text, 'lxml')
            pages = soup1.select('#list_D10_01 > span > span')  # 页数
            print('http://esf.xian.fang.com' + regions[n].get('href') + '-' + housetypes[i].get('href')[7:], pages[0].get_text().split('/')[1])
            i = i + 1
        n = n + 3         # 只取1/4/7
    

    根据其生成的页码数,对于达到100页的再进行细分,先用“总价”,再用“面积”,这样一级一级拆分下去,最终使得每一个细分项对应的页数都在100以内,然后再通过上一篇里面从零开始学爬虫(1):爬取房天下二手房信息的讲到的爬虫主函数去逐页爬取(对于其中细分项为空的页面直接略过)即可:

    # 对于大于等于100页的进行细分
    n = 1
    while n < 8:
        i = 1
        while i < 7:
            resp1 = requests.get('http://esf.xian.fang.com' + regions[n].get('href') + '-' + housetypes[i].get('href')[7:], headers=headers)
            soup1 = BeautifulSoup(resp1.text, 'lxml')
            pages = soup1.select('#list_D10_01 > span > span')  # 页数
            if pages and pages[0].get_text().split('/')[1] == '100':
                m = 1
                while m < 10:
                    resp1 = requests.get('http://esf.xian.fang.com' + regions[n].get('href') + totprices[m].get('href')[7:-1] + '-' + housetypes[i].get('href')[7:], headers=headers)
                    soup1 = BeautifulSoup(resp1.text, 'lxml')
                    pages = soup1.select('#list_D10_01 > span > span')  # 页数
                    if pages and pages[0].get_text().split('/')[1] == '100':
                        j = 1
                        while j < 10:
                            resp1 = requests.get('http://esf.xian.fang.com' + regions[n].get('href') + totprices[m].get('href')[7:-1] + '-' + housetypes[i].get('href')[7:-1] + '-' + areas[j].get('href')[7:], headers=headers)
                            soup1 = BeautifulSoup(resp1.text, 'lxml')
                            pages = soup1.select('#list_D10_01 > span > span')  # 页数
                            if pages:
                                k = int(pages[0].get_text().split('/')[1])
                                while k > 0:
                                    spider_1('http://esf.xian.fang.com' + regions[n].get('href') + totprices[m].get('href')[7:-1] + '-' + housetypes[i].get('href')[7:-1] + '-' + areas[j].get('href')[7:-1] + '-i3' + str(k))
                                    k = k - 1
                                    time.sleep(2)
                            else:
                                pass
                            j = j + 1
                    else:
                        if pages:
                            k = int(pages[0].get_text().split('/')[1])
                            while k > 0:
                                spider_1('http://esf.xian.fang.com' + regions[n].get('href') + totprices[m].get('href')[7:-1] + '-' + housetypes[i].get('href')[7:-1] + '-i3' + str(k))
                                k = k - 1
                                time.sleep(2)
                        else:
                            pass
                    m = m + 1
            else:
                if pages:
                    k = int(pages[0].get_text().split('/')[1])
                    while k > 0:
                        spider_1('http://esf.xian.fang.com' + regions[n].get('href') + housetypes[i].get('href')[7:-1] + '-i3' + str(k))
                        k = k - 1
                        time.sleep(2)
                else:
                    pass
            i = i + 1
        n = n + 3         # 只取1/4/7
    

    四、后记

    这样爬下来的数据量太大,最好直接导出到本地存储,那么具体如何操作呢?
      据说MongoDB是个不错的选择,容我先去学习学习……

    相关文章

      网友评论

      • 小佰姓:一件小事 坚持久了就会有奇迹

      本文标题:从零开始学爬虫(2):突破限制,分类爬取,获得全部数据

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