本文在有些需要解释说明的地方引用了知乎文章屌丝想买房……和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
,在终端观察导入情况,若有报错,则排除问题,若成功写入, 则本次试验到此结束。若有数据库编码问题,可尝试自行解决。