本文在有些需要解釋說明的地方引用了知乎文章屌絲想買房……和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,不修改爬不了任何數據).
- 2、添加瀏覽器代理
- 3、取消注釋
以下代碼使用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('  ')
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
,在終端觀察導入情況,若有報錯,則排除問題,若成功寫入, 則本次試驗到此結束。若有數據庫編碼問題,可嘗試自行解決。