Scrapy実戦編(一)の爬取チェーン家網成約住宅源データ(上)

8195 ワード

今日、私たちはチェーン家網南京地区を例に、チェーン家網の成約住宅源データを勉強します.
ここでは火狐ブラウザをお勧めし、firebugとfirepathの2つのプラグインをインストールします.この2つのプラグインは、後続のデータ抽出に大きな便利さをもたらします.
まずlianjiaという名前のプロジェクトを作成します.
需要分析
データの第一歩を登るのはもちろん私达の需要を确定するので、大きい方向は私达が南京地区の住宅の源の成约の情报を手に入れたいので、しかし具体的な详しい情报、私达はホームページから见て、私达は直接ブラウザの中で以下のウェブサイトを入力する必要がありますhttps://nj.lianjia.com/chengjiao/、南京地区の成約の住宅源の情報を表示して、名称、家屋の紹介を含んで、地理的位置、成約日、成約価格、成約単価などの詳細は、items.pyファイルで以下のフィールドを定義します.
#items.py
from scrapy import Item,Field

class LianjiaItem(Item):
    region = Field()      #    
    href = Field()        #    
    name = Field()        #    
    style = Field()       #    
    area = Field()           #  
    orientation = Field()    #  
    decoration = Field()     #  
    elevator = Field()       #  
    floor = Field()          #    
    build_year = Field()     #    
    sign_time = Field()      #    
    unit_price = Field()     #     
    total_price = Field()    #  
    fangchan_class = Field()   #    
    school = Field()         #    
    subway = Field()         #    

以上の情報は、すべての住宅源があるわけではありません.例えば、下の地下鉄、学校、多くの住宅源はありません.
に質問
  • あなたは1つの问题を発见することができて、1つのページごとに30条の部屋の源の情报を现して、最も下は全部で100ページを表示することができて、総計は最大で3000条の情报で、南京地区の成约の部屋の源の情报はきっとこの区の3000条だけではありませんて、それでは直接このページをめくることを通じてデータを取得するならば、最大で3000条の情报を得ることができますだから私たちは考えを変える必要があります.
  • はまだこのページで、ページの上部に南京地区の行政区がリストされているのが見えます.私たちは勝手に1つを選んで、新しいページは依然として1ページ30本で、合計100ページですが、私たちは11の行政区を持っていて、その数も何倍も増えています.
  • この时、あなたはまだ満足していないかもしれませんが、私たちは方法を考えてみると、さらに下に分けることができますか?间违いなくそれは団地です.私たちは住宅源を11の行政区から団地に分けて、団地を単位にして、各団地の上に住宅源のデータがあります.そうすれば、私たちの情报は比较的全面的に言えます.もちろん、私たちがしなければならない仕事も2倍になります.

  • まとめ
    ここでは、分析を通じて、次のような考え方をまとめました.
  • 行政区単位で、まず南京地区のすべての団地情報
  • を取得する.
  • セル単位で、各セル内のセルソースデータ
  • を取得する.
  • は最後に、具体的な各住宅源の情報を取得する.

  • 具体的な実施
    今、私たちの考えを明確にして、次に具体的な実施を始めます.
    spider.pyファイルの作成
    from scrapy import Spider,Request
    import re
    from lxml import etree
    import json
    from urllib.parse import quote
    from lianjia.items import LianjiaItem
    
    class Lianjia_spider(Spider):
        name = 'lianjia'
        allowed_domains = ['nj.lianjia.com']
        regions = {'gulou':'  ',
                   'jianye':'  ',
                   'qinhuai':'  ',
                   'xuanwu':'  ',
                   'yuhuatai':'   ',
                   'qixia':'  ',
                   'jiangning':'  ',
                   'liuhe':'  ',
                   'pukou':'  ',
                   'lishui':'  ',
                   'gaochun':'  '
        }
    
        def start_requests(self):
            for region in list(self.regions.keys()):
                url = "https://nj.lianjia.com/xiaoqu/" + region + "/"
                yield Request(url=url, callback=self.parse, meta={'region':region}) #      
    
        def parse(self, response):
            region = response.meta['region']
            selector = etree.HTML(response.text)
            sel = selector.xpath("//div[@class='page-box house-lst-page-box']/@page-data")[0]  #          
            sel = json.loads(sel)  #      
            total_pages = sel.get("totalPage")
    
            for i in range(int(total_pages)):
                url_page = "https://nj.lianjia.com/xiaoqu/{}/pg{}/".format(region, str(i + 1))
                yield Request(url=url_page, callback=self.parse_xiaoqu, meta={'region':region})
    
        def parse_xiaoqu(self,response):
            selector = etree.HTML(response.text)
            xiaoqu_list = selector.xpath('//ul[@class="listContent"]//li//div[@class="title"]/a/text()')
            for xq_name in xiaoqu_list:
                url = "https://nj.lianjia.com/chengjiao/rs" + quote(xq_name) + "/"
                yield Request(url=url, callback=self.parse_chengjiao, meta={'xq_name':xq_name, 
                                        'region':response.meta['region']})
    
        def parse_chengjiao(self,response):
            xq_name = response.meta['xq_name']
            selector = etree.HTML(response.text)
            content = selector.xpath("//div[@class='page-box house-lst-page-box']")  #     
            total_pages = 0
            if len(content):
                page_data = json.loads(content[0].xpath('./@page-data')[0])
                total_pages = page_data.get("totalPage")  #         
            for i in range(int(total_pages)):
                url_page = "https://nj.lianjia.com/chengjiao/pg{}rs{}/".format(str(i+1), quote(xq_name))
                yield Request(url=url_page, callback=self.parse_content, meta={'region': response.meta['region']})
    
        def parse_content(self,response):
            selector = etree.HTML(response.text)
            cj_list = selector.xpath("//ul[@class='listContent']/li")
    
    
            for cj in cj_list:
                item = LianjiaItem()
                item['region'] = self.regions.get(response.meta['region'])
                href = cj.xpath('./a/@href')  
                if not len(href):
                    continue
                item['href'] = href[0]
    
                content = cj.xpath('.//div[@class="title"]/a/text()') 
                if len(content):
                    content = content[0].split()  #            
                    item['name'] = content[0]
                    item['style'] = content[1]
                    item['area'] = content[2]
    
                content = cj.xpath('.//div[@class="houseInfo"]/text()')
                if len(content):
                    content = content[0].split('|')
                    item['orientation'] = content[0]
                    item['decoration'] = content[1]
                    if len(content) == 3:
                        item['elevator'] = content[2]
                    else:
                        item['elevator'] = ' '
    
                content = cj.xpath('.//div[@class="positionInfo"]/text()')
                if len(content):
                    content = content[0].split()
                    item['floor'] = content[0]
                    if len(content) == 2:
                        item['build_year'] = content[1]
                    else:
                        item['build_year'] = ' '
    
                content = cj.xpath('.//div[@class="dealDate"]/text()')
                if len(content):
                    item['sign_time'] = content[0]
    
                content = cj.xpath('.//div[@class="totalPrice"]/span/text()')
                if len(content):
                    item['total_price'] = content[0]
    
                content = cj.xpath('.//div[@class="unitPrice"]/span/text()')
                if len(content):
                    item['unit_price'] = content[0]
    
                content = cj.xpath('.//span[@class="dealHouseTxt"]/span/text()')  
                if len(content):
                    for i in content:
                        if i.find("   ") != -1:  #         -1  ,        -1
                            item['fangchan_class'] = i
                        elif i.find("  ") != -1:
                            item['subway'] = i
                        elif i.find(" ") != -1:
                            item['school'] = i
                yield item
    
    

    私たちは上の重要な点について説明します.
  • start_requestsこれは私たちが行政区単位で、各行政区の団地のリストを登ることを目的としています.
  • parseは行政区が返すresponseを解析し、この大きな行政区を手に入れることを目的としています.何ページが含まれていますか.そのうちtotal_pagesは具体的なページ数で、次はページ番号に従って各ページを要求します.
  • parse_xiaoquには各ページの情報が返され、このとき現在のページのセルリストを取得し、その後、セルリストに対して各セルに対して要求を行う.
  • parse_chengjiao解析セルのページ数,前述したように,各セルデータを要求したが,このセルには必ず1ページのデータだけが含まれているわけではないので,この方法はこのセルに含まれるページ数を抽出し,各ページについて
  • を求める.
  • parse_contentという方法は具体的なページを解析することです.この方法には非常に多くの条件判断が含まれています.これは、私たちが定義したitemフィールドの情報が、団地ごとにあるわけではありません.つまり、私たちが望んでいる情報は、彼は規則正しい情報ではありません.多くの住宅源は地下鉄などの関連情報を提供していません.周辺の学校などの情報は、この情報があれば抽出し、なければカスタマイズしてあげます.最後にitemをitem pipelineにコミットして後続の処理を行う.

  • このセクションの情報が多いので、2つのセクションに分けて、次のセクションでは、取得したデータについて後続の処理を行います.