scrapy新手入门爬虫(链家小区信息)
来源:互联网 发布:淘宝上架宝贝没有品牌 编辑:程序博客网 时间:2024/04/30 21:39
新手python3自学爬虫1个星期,期间遇到各种坑,还参考各种文章,以及让高手远程帮助,总算完成了简单的爬虫,现在总结一下各种经验,文章里可能有描述的不对的地方,请各位指正
开发的工具:python36,scrapy,beautifulsoup,pymysql
安装问题细节可以看一下别的教程,我这里大致说一下遇到的坑
首先python安装的时候如果你没有勾环境变量 ,需要去环境变量path里设置,下面是我的变量,就是装python的地址,然后后面的scripts也要声明一下,可以方便以后用pip装东西。
python安装验证
验证的话可以在开始-附件-运行里输入cmd,然后输入python,如果出现python版本,说明装好了。
pip怎么用?
直接开始-附件-运行里输入cmd,然后输入如:pip install Scrapy,就可以看到模块会自动安装。如果运行的时候错误,可以去环境变量里看看scripts是否加进去了
我的path E:\Python\Python36;E:\Python\Python36\Scripts
scrapy可以用pip install Scrapy
scrapy装的时候可能会遇到 error: Microsoft Visual C++ 14.0 is required
下载twisted,ctrl+f找到对应的版本:http://www.lfd.uci.edu/~gohlke/pythonlibs/#wordcloud
还会遇到 no module named win32api
原因是缺少win32,到 http://sourceforge.net/projects/pywin32/files/
mysql安装,注意要用小写,还可以用其他的mysql相关模块,反正python3里这个肯定是没问题
pip install pymysql
继续装 pip install beautifulsoup4
一般如果还遇到什么问题,可以看看cmd里红字的提示缺少什么,百度一下就ok
下面正式写程序
在cmd里输入scrapy startproject lianjia创建scrapy爬虫工程,比如我要建在d盘的根目录,在命令行输入cd e: 回车scrapy startproject lianjia回车,就创建好了,目录结构为D:\lianjia\lianjia\spiders,然后在spiders文件夹里创建lianjia.py文件
#导入第三方模块# -*- coding: utf-8 -*-import scrapyfrom bs4 import BeautifulSoupimport pymysql
#name为一会儿要运行的爬虫名,格式为:scrapy crawl lianjia#allowed_domains为域名,控制爬虫的爬取范围,但是这里有可能会产生一个bug,某些情况域名限制了数据的输,只能传一条,比如for i in['aaa','bbb'],print(i),只会拿到一个aaa的值,解决方就是在yield后面加上dont_filter=True,让域的限制消失#start_urls 开始页,但是本次爬虫并没有用到#上面三个应该是scrapy的格式#server及sec是为了爬取设置的网址class lianjia(scrapy.Spider): name = "lianjia" allowed_domains = ['http://sh.lianjia.com'] start_urls = ['http://sh.lianjia.com/zufang/'] server = 'http://sh.lianjia.com/xiaoqu/d' sec = 'http://sh.lianjia.com'
#注意第一个函数名一定要为parse,response就是从上一项拿到的值,当然也可以改成aaaa这种都没问题。然后可以打印一下respense,看一下值是什么。<200 http://sh.lianjia.com/zufang/>,一般来说如果要用到首页的话下面就可以直接用xpath解析了#page_num为需要爬取的页数,然后for历遍一下,并拼在server的后面,所以能得到的值为http://sh.lianjia.com/xiaoqu/d1,注意拼的时候i一定要用str先转成字符串类型,不转的话是数字类型会报错,可以print (link)打印一下看网页内容#yield scrapy.Request就是一个传递的参数有下面的只介绍3个,url=需要传递的值,callback=传递给哪个函数,dont_filter=True不启用域的限制 def parse(self, response): page_num = 1 for i in range(1, page_num + 1): link = self.server + str(i) yield scrapy.Request(url=link, callback=self.parse2, dont_filter=True)
#zu_fang解析parse传过来的各种网页,就是http://sh.lianjia.com/xiaoqu/d1,如果不清楚的话可以打开网页,通过检查方式看,response.xpath就是用xpath模式解析,//li就是li开头/div/a是li后面的目录结构,然后通过@来获取a里的href的值(如果要取文本的话可以用text()),extract()全部显示[:1]取第一个找到的,这部分可以单独百度一下xpath#之后的解释都和上面是一样的,就是获取lianjia上的d1页面上每一个小区里的链接地址 def parse2(self, response): zu_fang = response.xpath('//li/div/a/@href').extract()[:1] for link in zu_fang: linka = self.sec + link print (linka) yield scrapy.Request(url=linka, callback=self.parse3, dont_filter=True)
#最后根据解析的地址找到相关的的标签,这里用到的第三方类beauifulsoup,解释一下逻辑,拿到从parse2传递过来的值,通过xpath解析,然后转换成beautifulsoup格式,下面的都是通过soup去找的各种字段类型,具体的可以看一下soup的各种文档#我以这条为例说一下意思,soupa = soup.find_all('div', class_="nav-container detail-container")[0]#soup.find_all找soup变量的所有div标签,并且class="nav-container detail-container"的相关内容[0]表示取拿到的第一个值#district = soupa.span.span.string,找到soupa下的第一个span标签,并再往下一层在span的标签里找第一个span标签,然后用string把值显示出来#replace('\\n', '').replace('\\t', '').strip() 去除字段中的\n,\t及空格的意思,这里用\\就是转义的意思,\\=\,或者也可以用r,如replace(r'\n', '').replace(r'\t', '').strip() def parse3(self, response): zufang = response.xpath('//body').extract() soup = BeautifulSoup(str(zufang), 'lxml') village = soup.h1.string soupa = soup.find_all('div', class_="nav-container detail-container")[0] district = soupa.span.span.string address = soupa.span.find_all('span')[1].string price = soup.find_all('div', class_="item col1")[0].span.string.replace('\\n', '').replace('\\t', '').strip() type = soup.find_all('div', class_="col-2 clearfix")[0].li.span.string.replace('\\n', '').replace('\\t', '').strip() age = soup.find_all('div', class_="col-2 clearfix")[0].find_all('span')[2].string.replace('\\n', '').replace('\\t','').strip() fee = soup.find_all('div', class_="col-2 clearfix")[0].find_all('span', class_='other')[2].string.replace('\\n','').replace('\\t', '').strip() estate = soup.find_all('div', class_="col-2 clearfix")[0].find_all('span', class_='other')[3].string.replace('\\n','').replace( '\\t', '').strip() developer = soup.find_all('div', class_="col-2 clearfix")[0].find_all('span', class_='other')[4].string.replace( '\\n', '').replace('\\t', '').strip() district2 = soup.find_all('div', class_="col-2 clearfix")[0].find_all('span', class_='other')[5].string ring = soup.find_all('div', class_="col-2 clearfix")[0].find_all('span', class_='other')[6].string.replace('\\n','').replace('\\t', '').strip()
# 打开数据库连接,charset="utf8"必须加,不然如果爬到的是中文字,插不进数据库 db = pymysql.connect("数据库地址", "用户", "密码", "库名", charset="utf8") # 使用cursor()方法获取操作游标 cursor = db.cursor() # SQL 插入语句,如果插入遇到问题可以看一下表设置的最大字段长度是否过短 sql = """INSERT INTO village_info_lianjia(village,district,address,price,type,age,fee,estate,developer,district2,ring,source) VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')"""%(village,district,address,price,type,age,fee,estate,developer,district2,ring,'lianjia') try: # 执行sql语句 cursor.execute(sql) # 提交到数据库执行 db.commit() except: # 如果发生错误则回滚 db.rollback() # #关闭数据库连接 db.close()
完整的数据代码
# -*- coding: utf-8 -*-import scrapyfrom bs4 import BeautifulSoupimport pymysqlclass lianjia(scrapy.Spider): name = "lianjia" allowed_domains = ['http://sh.lianjia.com'] start_urls = ['http://sh.lianjia.com/zufang/'] server = 'http://sh.lianjia.com/xiaoqu/d' sec = 'http://sh.lianjia.com' def parse(self, response): page_num = 1 for i in range(1, page_num + 1): link = self.server + str(i) yield scrapy.Request(url=link, callback=self.parse2, dont_filter=True) def parse2(self, response): zu_fang = response.xpath('//li/div/a/@href').extract()[:1] for link in zu_fang: linka = self.sec + link print (linka) yield scrapy.Request(url=linka, callback=self.parse3, dont_filter=True) def parse3(self, response): zufang = response.xpath('//body').extract() soup = BeautifulSoup(str(zufang), 'lxml') village = soup.h1.string soupa = soup.find_all('div', class_="nav-container detail-container")[0] district = soupa.span.span.string address = soupa.span.find_all('span')[1].string price = soup.find_all('div', class_="item col1")[0].span.string.replace('\\n', '').replace('\\t', '').strip() type = soup.find_all('div', class_="col-2 clearfix")[0].li.span.string.replace('\\n', '').replace('\\t', '').strip() age = soup.find_all('div', class_="col-2 clearfix")[0].find_all('span')[2].string.replace('\\n', '').replace('\\t','').strip() fee = soup.find_all('div', class_="col-2 clearfix")[0].find_all('span', class_='other')[2].string.replace('\\n','').replace('\\t', '').strip() estate = soup.find_all('div', class_="col-2 clearfix")[0].find_all('span', class_='other')[3].string.replace('\\n','').replace( '\\t', '').strip() developer = soup.find_all('div', class_="col-2 clearfix")[0].find_all('span', class_='other')[4].string.replace( '\\n', '').replace('\\t', '').strip() district2 = soup.find_all('div', class_="col-2 clearfix")[0].find_all('span', class_='other')[5].string ring = soup.find_all('div', class_="col-2 clearfix")[0].find_all('span', class_='other')[6].string.replace('\\n','').replace('\\t', '').strip() db = pymysql.connect("数据库地址", "用户", "密码", "库名", charset="utf8") cursor = db.cursor() sql = """INSERT INTO village_info_lianjia(village,district,address,price,type,age,fee,estate,developer,district2,ring,source)VALUES('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')"""%(village,district,address,price,type,age,fee,estate,developer,district2,ring,'lianjia') try: cursor.execute(sql) db.commit() except: db.rollback() db.close()
mysql建表命令
CREATE TABLE `village_info_lianjia` ( `village` varchar(30) DEFAULT NULL, `district` varchar(30) DEFAULT NULL, `address` varchar(300) DEFAULT NULL, `price` varchar(30) DEFAULT NULL, `type` varchar(30) DEFAULT NULL, `age` varchar(30) DEFAULT NULL, `fee` varchar(30) DEFAULT NULL, `estate` varchar(30) DEFAULT NULL, `developer` varchar(30) DEFAULT NULL, `district2` varchar(30) DEFAULT NULL, `ring` varchar(300) DEFAULT NULL, `source` varchar(30) DEFAULT NULL)
最后忘记说了page_num = 1 是页数。1代表http://sh.lianjia.com/xiaoqu/d1,2代表http://sh.lianjia.com/xiaoqu/d2等以此类推
lianjia的网址每页都有20条房子数据,我代码只取了第一条,所以如果你爬完整的话,需要把1改成20
如:
zu_fang = response.xpath(‘//li/div/a/@href’).extract()[:20]
最后再说一下scrapy执行命令
cd进链家的目录
比如我的目录结构是D:\lianjia\lianjia\spiders
那我在cmd的时候就先cd D:回车cd lianjia回车,直接输入scrapy crawl lianjia
其中lianjia是爬虫的name
name = “lianjia”
- scrapy新手入门爬虫(链家小区信息)
- Scrapy爬虫(一)
- Scrapy爬虫(一)
- Scrapy爬虫(未完)
- Scrapy爬虫实战二:获取天气信息
- Scrapy爬虫入门教程四 Spider(爬虫)
- 爬虫-scrapy安装(新)
- scrapy爬虫精要(1)
- scrapy爬虫精要(2)
- scrapy爬虫精要(3)
- 浅谈 Scrapy 爬虫(二)
- python爬虫框架(scrapy)
- scrapy 爬虫入门(1)
- 爬虫知识点(scrapy框架)
- Scrapy系列教程(3)------Spider(爬虫核心,定义链接关系和网页信息抽取)
- Scrapy爬虫实践之搜索并获取前程无忧职位信息(基础篇)
- 【图文详解】scrapy爬虫与动态页面——爬取拉勾网职位信息(1)
- 【图文详解】scrapy爬虫与动态页面——爬取拉勾网职位信息(2)
- Camera CullingMask层处理
- Java反射 Filed.get(null)
- 封装数据出错-->字符串-时间
- 简陋月考题
- Laravel-使用富文本编辑器UEditor
- scrapy新手入门爬虫(链家小区信息)
- Rinex电文读取与定位解算
- Android HttpURLConnection 多线程下载
- MySQL定时执行脚本(计划任务)命令实例
- 嵌入式开发工程师修炼步骤
- 迪杰斯特拉算法模板
- 获取手机文件路径
- 数据集成学习笔记 --- DataX学习笔记
- 联合单点登录(Federated Single Sign-On)概念辨析