scrapy爬取上海鏈家網35000條在租房信息并導入數據庫

本文在有些需要解釋說明的地方引用了知乎文章屌絲想買房……Scrapy入門教程

本篇教程中將按照下列五步實現標題所述目標:

1、創建一個Scrapy項目

本篇建議安裝Anaconda3,Anaconda可以很方便地解決多版本python并存、切換以及各種第三方包安裝問題。Anaconda利用工具/命令conda來進行package和environment的管理,并且已經包含了Python和相關的配套工具。

  • 1、新建項目: scrapy startproject lianjia
  • 2、切換目錄:cd lianjia
  • 3、新建爬蟲:scrapy genspider Ljia sh.lianjia.com/zufang

工程文件說明:
scrapy.cfg 記錄項目的配置信息
items.py 存放爬取完數據的模板,用于結構化數據
pipelines 數據處理行為,比如結構化的數據,存放到數據庫持久化等等
settings.py 配置文件,比如遞歸的層數、并發數,延遲下載等
spiders 真正干活的爬蟲目錄,對網頁的數據清洗

2、定義提取的Item

Item是我們要爬取數據的模板,因此我們應該先編輯lianjia/lianjia下的items文件
觀察我們要爬取的在租房示例圖,首先想好你要爬取哪些關鍵信息


在租房示例圖

我定義的目標提取字段比較詳細(也可以說比較啰嗦),字段含義參考代碼注釋


# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class LianjiaItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()      #房間標題,例如:申金大廈,好樓層,鑰匙在鏈家,鏈家好房
    roomType = scrapy.Field()   #房間類型,幾室幾廳
    roomName = scrapy.Field()   #房間名,例如:申金大廈
    roomPrice = scrapy.Field()  #價格,按月為單位
    roomStatus = scrapy.Field() #房間狀態,例如:隨時看房
    roomDate = scrapy.Field()   #房間上架日期,例如:2017.08.06
    areaB = scrapy.Field()      #區域   例如:浦東,黃浦
    street = scrapy.Field()     #街道,例如:距離5號線金平路站794米

3、編寫爬取網站的spider并提取Item

網頁解析

租房信息
網頁源碼

可以看到網頁元素還是很好抽取的,但是我們要先做一些準備工作

  • 1、把setting.py里面的ROBOT協議尊守改為False,不修改爬不了任何數據).
settings.py
  • 2、添加瀏覽器代理
取消這塊代碼的注釋并添加瀏覽器的代理
  • 3、取消注釋
image.png

以下代碼使用xpath提取目標字段,xpath是抽取HTML元素最為便捷和快捷的方式,關于xpath的使用參考xpath語法


# -*- coding: utf-8 -*-
import scrapy
import re
from lianjia.items import LianjiaItem

class LjiaSpider(scrapy.Spider):
    name = 'Ljia'
    allowed_domains = ['https://sh.lianjia.com/zufang']
    start_urls = ['https://sh.lianjia.com/zufang']
    

    def parse(self, response):
        for i in response.xpath('.//li/div[@class="info-panel"]'):
            item = LianjiaItem()
            item['title'] = i.xpath('.//h2/a/@title').extract_first()
            item['roomName'] = i.xpath('.//div[@class="where"]/a/span/text()').extract_first()
            item['roomType'] = i.xpath('.//div[@class="where"]/span/text()').extract_first().rstrip(' &nbsp')
            roomDesc = i.xpath('.//div[@class="con"]').extract_first()
            item['roomPrice'] = i.xpath('.//div[@class="price"]/span/text()').extract_first()
            item['roomStatus'] = i.xpath('.//span[@class="anytime-ex"]/span/text()').extract_first()
            item['roomDate'] = i.xpath('.//div[@class="col-3"]/div[@class="price-pre"]/text()').extract_first().rstrip('7\n\t\t\t\t\t\t\t上架')
            item['areaB'] = str(i.xpath('.//div[@class="con"]/a/text()').extract()[0])
            item['street'] = i.xpath('.//span[@class="fang-subway-ex"]/span/text()').extract_first()
            yield item
        temp_url = response.xpath('//a[@gahref="results_next_page"]/@href').extract()[0]
        if temp_url:
            url = 'https://sh.lianjia.com' + temp_url
        yield scrapy.Request(url=url, callback=self.parse, dont_filter=True)

注釋:extract_first()方法用來序列化抽取到的網頁元素,dont_filter字段用于避免服務器把我們的爬蟲url做重定向

4、編寫Item PipeLine來存儲提取到的Item(即數據)

/lianjia/lianjia/pipelines 文件

import pymysql 

class LianjiaPipeline(object):
    
    def __init__(self):
        self.conn = pymysql.connect(host='localhost', user='root', passwd='****', \
                                   db='***', charset='utf8')
        self.cur = self.conn.cursor()
        
    def process_item(self, item, spider):
        
        title = item.get('title', 'N/A')
        roomType = item.get('roomType', 'N/A')
        roomName = item.get('roomName', 'N/A')
        #roomSize = item.get('roomSize', 'N/A')
        #roomDesc = item.get('roomDesc', 'N/A')
        roomPrice = item.get('roomPrice', 'N/A')
        roomStatus = item.get('roomStatus', 'N/A')
        roomDate = item.get('roomDate', 'N/A')
        areaB = item.get('areaB', 'N/A')
        street = item.get('street', 'N/A')
        
        sql = 'insert into lianjia(title, roomType, roomName, roomPrice, \
                roomStatus, roomDate, areaB, street) values(%s, %s, %s, %s, %s, %s, %s, %s)'
        self.cur.execute(sql, (title, roomType, roomName, roomPrice, roomStatus, roomDate,areaB, street))
        self.conn.commit()
        #return item
        
    def close_spider(self, spider):
        self.cur.close()
        self.conn.close()

注釋:
1、安裝pymysql包:pip install pymysql
2、self.cur(游標對象)用于對數據表操作,self.conn(數據庫對象)用于提交對數據庫的操作

5、讓爬蟲動起來

上面的爬蟲工程已經準備好了,現在可以運行一下等待結果了

  • 初步調試階段:
    先注釋掉pipelines文件中的sql執行語句,執行命令scrapy crawl Ljia -o house.csv做初步調試,不著急導入數據庫,在終端觀察爬蟲運行情況,若出現報錯則查看錯誤信息進行故障排查,若爬取成功則打開lianjia目錄下面的house.csv文件查看爬取結果
部分結果
  • 數據庫導入階段:
    若上面執行成功,則開始導入數據庫,取消注釋sql語句,執行命令scrapy crawl Ljia,在終端觀察導入情況,若有報錯,則排除問題,若成功寫入, 則本次試驗到此結束。若有數據庫編碼問題,可嘗試自行解決。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容