数据采集第四次大作业

第四次大作业

作业1

1.1实验题目

  • 要求:熟练掌握 scrapy 中 Item、Pipeline 数据的序列化输出方法;Scrapy+Xpath+MySQL数据库存储技术路线爬取当当网站图书数据

  • 候选网站:http://search.dangdang.com/?key=python&act=input

  • 关键词:学生可自由选择

  • 输出信息:MySQL的输出信息如下

    avatar

1.2思路

1.2.1分析查找过程

​ 通过对页面检查可以发现,每本书的信息都存储在li标签下

​ 所以通过爬取每个li标签的内容存储再lis

lis = selector.xpath("//li['@ddt-pit'][starts-with(@class,'line')]")

​ 再对每个li标签下的内容进行分析,通过xpath得到所需部分的内容

title = li.xpath("./a[position()=1]/@title").extract_first() #书名
price = li.xpath("./p[@class='price']/span[@class='search_now_price']/text()").extract_first() #价格
author = li.xpath("./p[@class='search_book_author']/span[position()=1]/a/@title").extract_first()#作者
date = li.xpath("./p[@class='search_book_author']/span[position()=last()- 1]/text()").extract_first()#日期
publisher =li.xpath("./p[@class='search_book_author']/span[position()=last()]/a/@title").extract_first()#出版社
detail = li.xpath("./p[@class='detail']/text()").extract_first()#简介

​ 爬取完一页信息后,进行翻页,通过flag的大小来限定翻页的个数,这里只爬取了三页的信息

if self.flag<2:
	self.flag+=1
	url = response.urljoin(link)
	yield scrapy.Request(url=url, callback=self.parse)

1.2.2items.py编写

title = scrapy.Field()
author = scrapy.Field()
date = scrapy.Field()
publisher = scrapy.Field()
detail = scrapy.Field()
price = scrapy.Field()

1.2.3 pipelines.py编写

​ 先与数据库进行连接,并且如果表不存在就创建表,如果表存在就先删除表再创建

self.con = sqlite3.connect("dangdand.db")
self.cursor = self.con.cursor()
	# 创建表
	try:
		self.cursor.execute("drop table book")
	except:
		pass
self.cursor.execute(
"create table book(bTitle varchar(512), bAuthor varchar(256),bPublisher varchar(256), bDate varchar(32), bPrice varchar(16), bDetail varchar(1024))")

​ 关闭数据库和spider

if self.opened:
	self.con.commit()
	self.con.close()
	self.opened = False

​ 向表中插入数据

if self.opened:
	#插入数据
	self.cursor.execute("insert into book(bTitle,bAuthor,bPublisher,bDate,bPrice,bDetail) values(?,?,?,?,?,?)",(item["title"],item["author"],item["publisher"],item["date"],item["price"],item["detail"]))
	self.count += 1

1.2.4运行scrapy框架代码

方法一:在scrapy框架中编写一个函数

from scrapy import cmdline
cmdline.execute("scrapy crawl Myspider -s LOG_ENABLED=False".split())

​ 其中Myspider要根据自己创建的spider python中的名字改

 name = 'Myspider'

​ 就是根据这句话中的名字进行修改,不是都是MySpider

方法二:在命令行中进入spider框架下,输入spider crawl Myspider进行运行,同样Myspider要根据自己的修改。

1.2.5 运行结果

数据库中结果

命令行输出结果

1.3完整代码

https://gitee.com/q_kj/crawl_project/tree/master/dangdang

1.4小结

​ 第一题是复现代码,一开始出现的问题是,生成的spider框架中的start_url=['']再进行拼接成完整代码的过程中会出现错误,将[]去掉就可以正常运行,其他就没有什么问题了。

作业2

2.1实验题目

  • 要求:熟练掌握 scrapy 中 Item、Pipeline 数据的序列化输出方法;使用scrapy框架+Xpath+MySQL数据库存储技术路线爬取外汇网站数据。

  • 候选网站:招商银行网:http://fx.cmbchina.com/hq/

  • 输出信息:MySQL数据库存储和输出格式

    Id Currency TSP CSP TBP CBP Time
    1 港币 86.60 86.60 86.26 85.65 15:36:30
    2......

2.2思路

2.2.1分析查找过程

​ 通过对页面检查可以发现,每种货币的信息都存储在tr标签下

​ 在检查中发现是在tbody下的tr标签中,所以开始使用//*[@id="rightbox"]/table/tbody/tr来匹配,结果为空。然后通过查看页面的源代码发现

并没有tbody标签,所以最后使用下面的代码匹配所以tr标签

trs = selector.xpath('//div[@id="realRateInfo"]/table/tr')

​ 然后对tr标签下所需内容进行匹配

name = tr.xpath('.//td[1]/text()').extract() #交易币
TSP = tr.xpath('.//td[4]/text()').extract() #现汇卖出价
CSP = tr.xpath('.//td[5]/text()').extract() #现钞卖出价
TBP = tr.xpath('.//td[6]/text()').extract() #现汇买入价
CBP = tr.xpath('.//td[7]/text()').extract() #现钞买入价
time = tr.xpath('.//td[8]/text()').extract() #时间            

​ 但是第一个tr标签中的内容为表头,是不需要的内容,所以需要再次进行筛选,通过初始设置count=0,当count=0时就跳过,同时将count置为1,剩下的内容就可以存入item中进行后续工作。

2.2.2settings.py设置

​ 通过F12查看到user_agent内容,同时修改settings中对应位置内容

​ 修改robots协议部分为False

​ 将下面部分的注释去掉

2.2.3items.py编写

currency = scrapy.Field()
TSP = scrapy.Field()
CSP = scrapy.Field()
TBP =scrapy.Field()
CBP = scrapy.Field()
Time = scrapy.Field()

2.2.4 pipelines.py编写

​ 先与数据库进行连接,并且如果表不存在就创建表,如果表存在就先删除表再创建

self.con = sqlite3.connect("bank.db")
self.cursor = self.con.cursor()
	# 创建表
	try:
		self.cursor.execute("drop table bank")
	except:
		pass
self.cursor.execute("create table bank(Id int,Currency varchar(32), TSP varchar(32),CSP varchar(32), TBP varchar(32), CBP varchar(32), Time varchar(32))")

​ 关闭数据库和spider

if self.opened:
	self.con.commit()
	self.con.close()
	self.opened = False

​ 向表中插入数据

if self.opened:
	#插入数据
	self.cursor.execute("insert into bank(Id,Currency,TSP,CSP,TBP,CBP,Time) values(?,?,?,?,?,?,?)",(self.count,item["currency"], item["TSP"], item["CSP"], item["TBP"], item["CBP"], item["Time"]))
	self.count += 1

2.2.5结果

数据库结果信息

控制台输入信息

2.3完整代码

https://gitee.com/q_kj/crawl_project/tree/master/zsBank

2.4小结

​ 本题主要问题在于tr标签查找时,在检查中可以发现存在tbody标签,但是通过它进行匹配时又匹配不到结果,而在页面源代码中可以发现并没有tbody标签,所以通过去除它就可以正确匹配到结果。所以通过查看页面源代码可以更好的看到层次,检查中看到的可能不是真实的内容。

作业3

3.1实验题目

  • 要求:熟练掌握 Selenium 查找HTML元素、爬取Ajax网页数据、等待HTML元素等内容;使用Selenium框架+ MySQL数据库存储技术路线爬取“沪深A股”、“上证A股”、“深证A股”3个板块的股票数据信息。

  • 候选网站:东方财富网:http://quote.eastmoney.com/center/gridlist.html#hs_a_board

  • 输出信息:MySQL数据库存储和输出格式如下,表头应是英文命名例如:序号id,股票代码:bStockNo……,由同学们自行定义设计表头:

    序号 股票代码 股票名称 最新报价 涨跌幅 涨跌额 成交量 成交额 振幅 最高 最低 今开 昨收
    1 688093 N世华 28.47 62.22% 10.92 26.13万 7.6亿 22.34 32.0 28.08 30.2 17.55
    2......

3.2思路

3.2.1分析页面

​ 通过对页面检查可以发现,每种货币的信息都存储在tr标签下

​ 然后通过对每个tr标签进行分析得到所需要的内容

try:
	id=tr.find_element(by=By.XPATH,value='.//td[1]').text
except:
	id=0

​ 因为所需内容很多,这里只给出一个示例,其余在代码中都有。

3.2.2创建表

​ 因为需要爬取三个板块的信息,所以创建三个表用于存储三个板块的信息

#和数据库创建连接
self.con = sqlite3.connect("stock.db")
self.cursor = self.con.cursor()
	#如果表hushen存在就删除,否则什么都不做
	try:
		self.cursor.execute("drop table hushen")
	except:
		pass
    #创建hushen表
    try:
        self.cursor.execute("create table hushen(Id varchar (16),bStockNo varchar(32),bStockName varchar(32),bNewPirce varchar(32),bUP varchar(32),bDowm varchar(32),bNum varchar(32),bCount varchar(32),bampl varchar (32),bHighest varchar(32),bMin varchar(32),bTodayOpen varchar(32),bYClose varchar(32))")
	except:
        pass
	# 如果表shangzheng存在就删除,否则什么都不做
	try:
		self.cursor.execute("drop table shangzheng")
	except:
		pass
	#创建shangzheng表
	try:
		self.cursor.execute("create table shangzheng(Id varchar (16),bStockNo varchar(32),bStockName varchar(32),bNewPirce varchar(32),bUP varchar(32),bDowm varchar(32),bNum varchar(32),bCount varchar(32),bampl varchar (32),bHighest varchar(32),bMin varchar(32),bTodayOpen varchar(32),bYClose varchar(32))")
	except:
		pass
    # 如果表shenzheng存在就删除,否则什么都不做
	try:
		self.cursor.execute("drop table shenzheng")
	except:
		pass
	#创建shenzheng表
	try:
		self.cursor.execute("create table shenzheng(Id varchar (16),bStockNo varchar(32),bStockName varchar(32),bNewPirce varchar(32),bUP varchar(32),bDowm varchar(32),bNum varchar(32),bCount varchar(32),bampl varchar (32),bHighest varchar(32),bMin varchar(32),bTodayOpen varchar(32),bYClose varchar(32))")
	except:
		pass

3.2.3关闭数据库

try:
	self.con.commit()
	self.con.close()
	self.driver.close()
except Exception as err:
	print(err)

3.2.4向表中插入数据

​ 因为存在三张表,所以使用flag来标注不同的表,向不同的表中插入数据。

if flag==1:
    try:
        self.cursor.execute("insert into hushen(Id,bStockNo,bStockName,bNewPirce,bUP,bDowm,bNum,bCount,bampl,bHighest,bMin,bTodayOpen,bYClose) values (?,?,?,?,?,?,?,?,?,?,?,?,?)", (Id,bStockNo,bStockName,bNewPirce,bUP,bDowm,bNum,bCount,bampl,bHighest,bMin,bTodayOpen,bYClose))
        print("插入数据成功")
    except Exception as err:
        print(err)
# 如果flag为2就向shangzheng表中插入数据
elif flag==2:
    try:
        self.cursor.execute(
            "insert into shangzheng(Id,bStockNo,bStockName,bNewPirce,bUP,bDowm,bNum,bCount,bampl,bHighest,bMin,bTodayOpen,bYClose) values (?,?,?,?,?,?,?,?,?,?,?,?,?)",
            (
            Id, bStockNo, bStockName, bNewPirce, bUP, bDowm, bNum, bCount,bampl, bHighest, bMin, bTodayOpen, bYClose))
        print("插入数据成功")
    except Exception as err:
        print(err)
# 如果flag为3就向shenzheng表中插入数据
elif flag==3:
    try:
        self.cursor.execute(
            "insert into shenzheng(Id,bStockNo,bStockName,bNewPirce,bUP,bDowm,bNum,bCount,bampl,bHighest,bMin,bTodayOpen,bYClose) values (?,?,?,?,?,?,?,?,?,?,?,?,?)",
            (
            Id, bStockNo, bStockName, bNewPirce, bUP, bDowm, bNum, bCount,bampl, bHighest, bMin, bTodayOpen, bYClose))
        print("插入数据成功")
    except Exception as err:
        print(err)

3.2.5实现翻页

这里只爬取了两页的信息,证明可以翻页

if self.count < 1:
	self.count += 1
	nextPage = self.driver.find_element(by=By.XPATH, value='//*[@id="main-table_paginate"]/a[2]')
	time.sleep(10)
	nextPage.click()
	self.processSpider(flag)

3.2.6实现不同板块的爬取

nextStock=self.driver.find_element(by=By.XPATH,value='//*[@id="nav_sh_a_board"]/a')
self.driver.execute_script("arguments[0].click();", nextStock)

3.2.7结果

hushen表

shangzheng表

shenzheng表

3.3完整代码

https://gitee.com/q_kj/crawl_project/tree/master/forth

3.4小结

​ 在click()时遇到错误element click intercepted,通过https://laowangblog.com/selenium-element-click-intercepted.html中的方法将next.click()改为self.driver.execute_script("arguments[0].click();", next)成功解决问题。selenium在爬取时经常会出现不成功的现象,可能都是因为页面还没有加载出来,所以要sleep一下,可能就可以正常爬取出结果了

posted @ 2021-11-11 00:36  Q_Pumpkin  阅读(27)  评论(0编辑  收藏  举报