数据采集第四次作业

作业一:

(1)实验要求:

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

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

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

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

(2)题目分析:

①第一题要求我们爬取的是当当网,我们首先打开网站,查看网页源代码,找到我们要爬取的元素。

我发现当当网的每一个商品都是在一个li标签下:

商品的名称在a标签下的第一个title中:

商品的价格在p标签中的span标签中:

书本的作者、出版时间、出版社都在p标签中的不同的sapan标签下,需要我们分别取出

书本的简介在p标签中,但有的可能为空:

②完成上述分析后,我们就可以来编写爬虫程序了,因为题目要求用scrapy,所以我们先创建一个scrapy项目起名为dangdang,然后编写items.py:

1 class DangdangItem(scrapy.Item):
2     title = scrapy.Field()  #书本的名称
3     author = scrapy.Field()  #书本的作者
4     publisher = scrapy.Field()  #书本的出版社
5     date = scrapy.Field()  #书本的出版日期
6     price = scrapy.Field()  #书本的价格
7     detail = scrapy.Field()  #书本的简介

③编写爬虫程序:

 1 import scrapy
 2 from datacollect.dangdang.dangdang.items import DangdangItem
 3 from bs4 import BeautifulSoup
 4 from bs4 import UnicodeDammit
 5 
 6 class Exe4Spider(scrapy.Spider):
 7     name = "exe4"
 8     key = 'python cookbook'
 9     source_url='http://search.dangdang.com/'
10 
11     def start_requests(self):
12         url = Exe4Spider.source_url+"?key="+Exe4Spider.key
13         yield scrapy.Request(url=url,callback=self.parse)
14 
15     def parse(self, response):
16         try:
17             dammit = UnicodeDammit(response.body, ["utf-8", "gbk"])
18             data = dammit.unicode_markup
19             selector=scrapy.Selector(text=data)
20             lis=selector.xpath("//li['@ddt-pit'][starts-with(@class,'line')]")
21             for li in lis:
22                 title=li.xpath("./a[position()=1]/@title").extract_first()
23                 price = li.xpath("./p[@class='price']/span[@class='search_now_price']/text()").extract_first()
24                 author = li.xpath("./p[@class='search_book_author']/span[position()=1]/a/@title").extract_first()
25                 date = li.xpath("./p[@class='search_book_author']/span[position()=last()- 1]/text()").extract_first()
26                 publisher = li.xpath("./p[@class='search_book_author']/span[position()=last()]/a/@title ").extract_first()
27                 detail = li.xpath("./p[@class='detail']/text()").extract_first()
28                 #detail有时没有,结果None
29                 item=DangdangItem()
30                 item["title"]=title.strip() if title else ""
31                 item["author"]=author.strip() if author else ""
32                 item["date"] = date.strip()[1:] if date else ""  ##因为日期那里有一个"/",要特殊处理
33                 item["publisher"] = publisher.strip() if publisher else ""
34                 item["price"] = price.strip() if price else ""
35                 item["detail"] = detail.strip() if detail else ""
36                 yield item
37                 #最后一页时link为None
38             link=selector.xpath("//div[@class='paging']/ul[@name='Fy']/li[@class='next']/a/@href").extract_first()
39             if link:
40                 url=response.urljoin(link)
41                 yield scrapy.Request(url=url, callback=self.parse)
42 
43         except Exception as err:
44             print(err)

④建立一个MySQL数据库,用来存放我们上述爬取到的数据:

 1 import pymysql
 2 db = pymysql.connect(host='localhost', port=3306, user='root', password='自己的密码', charset='utf8')
 3 cursor = db.cursor()
 4 cursor.execute('CREATE DATABASE test4')
 5 sql = '''create table test4.books(
 6             id int not null primary key auto_increment comment '序号',
 7             bTitle varchar(512) not null comment '标题',
 8             bAuthor varchar(256) not null comment '作者',
 9             bPublisher varchar(256) not null comment '出版社',
10             bDate varchar(32) default null comment '日期',
11             bPrice varchar(16) not null comment '价格',
12             bDetail text not null comment '简介'
13 )'''
14 cursor.execute(sql)
15 db.close()

⑤编写pipelines.py,来连接我们数据库,并将数据存入:

 1 import pymysql
 2 class DangdangPipeline(object):
 3     opened = False
 4     count = 0
 5     def open_spider(self,spider):
 6         try:
 7             self.con = pymysql.connect(host = "localhost",port = 3306,user = "root",password = "自己的密码",database = "test4",charset = "utf8")
 8             self.cursor = self.con.cursor()
 9             self.opened = True
10         except Exception as err:
11             print(err)
12             self.opened = False
13 
14     def close_spider(self,spider):
15         if self.opened>0:
16             self.con.commit()
17             self.con.close()
18             self.opened = False
19         print("closed")
20         print("一共爬取",self.count,"本书籍")
21 
22     def process_item(self, item, spider):
23         try:
24             print(item["title"])
25             print(item["author"])
26             print(item["publisher"])
27             print(item["date"])
28             print(item["price"])
29             print(item["detail"])
30             print()
31             if self.opened:
32                 self.cursor.execute("insert into books(bTitle,bAuthor,bPublisher,bDate,bPrice,bDetail) values (%s,%s,%s,%s,%s,%s)",(item["title"],item["author"],item["publisher"],item["date"],item["price"],item["detail"]))
33                 self.count+=1
34         except Exception as err:
35             print(err)
36         return item

⑥编写run.py,来运行我们的爬虫程序:

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

⑦结果展示:

码云地址https://gitee.com/shuai321/data-acquisition/tree/master/作业4/exe4.1

(3)心得体会: 

第一题是课本的一个实例复现,scrpay也学习了一段时间了,通过该题目再一次复习了起来,对于XPath语句使用的也较为熟练,本次实验还加了存储到数据库,所以又学习了SQL语句,收获满满!

 

 

作业二:

 (1)实验要求:

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

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

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

    IdCurrencyTSPCSPTBPCBPTime
    1 港币 86.60 86.60 86.26 85.65 15:36:30
    2......            

 (2)题目分析:

①首先还是进入网站查看网页源代码,去找我们要爬取的数据:

我们发现他在div标签中的第二个tr标签中开始就有每个交易币的各种信息了,里面标红的分别的就是我们要爬取的信息了:

②我们然后就可以根据上述的分析来定义XPath将信息定位,下面为爬虫程序中的parse函数:

 1     def parse(self, response):
 2         try:
 3             dammit = UnicodeDammit(response.body, ["utf-8", "gbk"])
 4             data = dammit.unicode_markup
 5             selector=scrapy.Selector(text=data)
 6             trs=selector.xpath("//div[@id = \"realRateInfo\"]//tr")
 7             for tr in trs:
 8                 currency=tr.xpath("./td[@class = 'fontbold']/text()").extract_first()
 9                 tsp = tr.xpath("./td[@class = 'numberright'][1]/text()").extract_first()
10                 csp = tr.xpath("./td[@class = 'numberright'][2]/text()").extract_first()
11                 tbp = tr.xpath("./td[@class = 'numberright'][3]/text()").extract_first()
12                 cbp = tr.xpath("./td[@class = 'numberright'][4]/text()").extract_first()
13                 time = tr.xpath("./td[@align = 'center'][last()-1]/text()").extract_first()
14                 item=BankItem()
15                 item["currency"]=currency.strip() if currency else ""
16                 item["tsp"]=tsp.strip() if tsp else ""
17                 item["csp"] = csp.strip() if csp else ""
18                 item["tbp"] = tbp.strip() if tbp else ""
19                 item["cbp"] = cbp.strip() if cbp else ""
20                 item["time"] = time.strip() if time else ""
21                 yield item
22                 #最后一页时trnk为None
23             link=selector.xpath("//div[@class='paging']/ul[@name='Fy']/li[@class='next']/a/@href").extract_first()
24             if link:
25                 url=response.urljoin(link)
26                 yield scrapy.Request(url=url, callback=self.parse)
27         except Exception as err:
28             print(err)

③编写items.py:

1 import scrapy
2 
3 class BankItem(scrapy.Item):
4     currency = scrapy.Field()
5     tsp = scrapy.Field()
6     csp = scrapy.Field()
7     tbp = scrapy.Field()
8     cbp = scrapy.Field()
9     time = scrapy.Field()

④创建MySQL数据库,存放爬取到的信息:

 1 import pymysql
 2 db = pymysql.connect(host='localhost', port=3306, user='root', password='自己的密码', charset='utf8')
 3 cursor = db.cursor()
 4 cursor.execute('CREATE DATABASE test5')
 5 sql = '''create table test5.bankchange(
 6             id int not null primary key auto_increment comment '序号',
 7             Currency varchar(256) not null comment '交易币',
 8             TSP varchar(16) not null comment '现汇卖出价',
 9             CSP varchar(16) not null comment '现钞卖出价',
10             TBP varchar(16) default null comment '现汇买入币',
11             CBP varchar(16) not null comment '现钞买入币',
12             Time varchar(16) not null comment '时间'
13 )'''
14 cursor.execute(sql)
15 db.close()

⑤编写pipelines.py,连接数据库,并将爬取到的信息存入数据库:

 1 import pymysql
 2 class BankPipeline(object):
 3     opened = False
 4     def open_spider(self,spider):
 5         try:
 6             self.con = pymysql.connect(host = "localhost",port = 3306,user = "root",password = "自己的密码",database = "test5",charset = "utf8")
 7             self.cursor = self.con.cursor()
 8             self.opened = True
 9         except Exception as err:
10             print(err)
11             self.opened = False
12 
13     def close_spider(self,spider):
14         if self.opened>0:
15             self.con.commit()
16             self.con.close()
17             self.opened = False
18         print("closed")
19 
20     def process_item(self, item, spider):
21         try:
22             print(item["currency"],item["tsp"],item["csp"],item["tbp"],item["cbp"],item["time"])
23             if self.opened:
24                 self.cursor.execute("insert into bankchange(Currency,TSP,CSP,TBP,CBP,Time) values (%s,%s,%s,%s,%s,%s)",(item["currency"],item["tsp"],item["csp"],item["tbp"],item["cbp"],item["time"]))
25         except Exception as err:
26             print(err)
27         return item

⑥编写run.py(同上),运行爬虫,查看结果:

码云地址:https://gitee.com/shuai321/data-acquisition/tree/master/作业4/exe4.2

(3)心得体会:

第二题也是对于scrapy与XPath结合,然后存储到MySQL数据库中的一个综合应用。第二题虽然看似简单,但我遇到了两个问题:第一是在爬取数据后发现第一行是空的,没有存储到数据库中,经过检查发现,它是从第二个tr标签才开始是我们要的信息,第一个tr标签下是标题;第二个问题是刚开始使用tbody标签来定位,但是不知道为什么是空的,后来修改//tr,顺利解决问题,后续还要加强XPath的练习!

 

 

作业三:

(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......                        

 (2)题目分析:

①首先我们打开东方财富网首页,查看网页源代码:

因为题目要求我们爬取三个板块,通过查看“沪深A股”“上证A股”“深证A股”,发现他们三个的url如下所示:

http://quote.eastmoney.com/center/gridlist.html#hs_a_board

http://quote.eastmoney.com/center/gridlist.html#sh_a_board

http://quote.eastmoney.com/center/gridlist.html#sz_a_board

所以控制三个板块的代码如下:

1 def main():
2     str = ['hs','sh','sz']   ##控制爬取的三种股票
3     for i in str:
4         url = 'http://quote.eastmoney.com/center/gridlist.html#'+i+'_a_board'   #对应不同的url
5         start_spider(url)
6         # getInfo(url)

②接着分析网页源代码,通过XPath语句定位信息,首先可以发现所有的股票信息都是在tbody标签中,每一支股票又在一个tr标签中。

通过查看每一个tr标签,发现我们要爬取的信息全都在td标签中的不同位置,所以可以通过position()来进行定位,比较方便:

 

 1     for link in driver.find_elements(By.XPATH,'//tbody/tr'):
 2         count += 1
 3         num = link.find_element(By.XPATH,'./td[position()=2]').text    #编号
 4         name = link.find_element(By.XPATH,'.//td[@class="mywidth"]').text  #名称
 5         value = link.find_element(By.XPATH,'.//td[@class="mywidth2"]').text  # 最新价
 6         Quote_change= link.find_element(By.XPATH,'./td[position()=6]').text  # 涨跌幅
 7         Ups_and_downs = link.find_element(By.XPATH,'./td[position()=7]').text   # 涨跌额
 8         Volume = link.find_element(By.XPATH,'./td[position()=8]').text   # 成交量
 9         Turnover = link.find_element(By.XPATH,'./td[position()=9]').text    # 成交额
10         amplitude = link.find_element(By.XPATH,'./td[position()=10]').text  # 振幅
11         highest = link.find_element(By.XPATH,'./td[position()=11]').text   # 最高
12         lowest = link.find_element(By.XPATH,'./td[position()=12]').text  # 最低
13         today_begin = link.find_element(By.XPATH,'./td[position()=13]').text   #今开
14         last_day = link.find_element(By.XPATH,'./td[position()=14]').text   # 昨收

③在最开始的地方,我们创建要模拟浏览器:

1 chrome_options = Options()
2 chrome_options.add_argument('--headless')  # 设置启动时不可见
3 chrome_options.add_argument('--disable-gpu')  # 设置不使用GPU加速
4 driver = webdriver.Chrome(options=chrome_options)  # 创建Chrome浏览器

④定义一个函数用来控制翻页,每一个模块均可使用:

 1 def getpage(url):
 2     count=1
 3     start_spider(url)
 4     try:
 5         nextpage = driver.find_element(By.CLASS_NAME,"paginate_input")
 6         nextpage.clear()
 7         nextpage.send_keys(count)
 8         Button = driver.find_element(By.CLASS_NAME,"paginte_go")
 9         Button.click()
10         time.sleep(3)
11         count+=1
12         getpage(url)
13     except:
14         print("err")
15         time.sleep(3)
16         getpage(url)

⑤创建MySQL数据库,并且将我们爬取到的数据存入到数据库:

 1 import pymysql
 2 
 3 db = pymysql.connect(host='localhost', port=3306, user='root', password='自己的密码', charset='utf8')
 4 cursor = db.cursor()
 5 cursor.execute('CREATE DATABASE Stock')
 6 sql = '''create table Stock.stocks(
 7             count int not null primary key comment '序号',
 8             num varchar(16) not null comment '股票代码',
 9             name varchar(16) not null comment '股票名称',
10             value varchar(16) not null comment '最新报价',
11             Quote_change varchar(16) null comment '涨跌幅',
12             Ups_and_downs varchar(16) not null comment '涨跌额',
13             Volume varchar(16) not null comment '成交量',
14             Turnover varchar(16) not null comment '成交额',
15             amplitude varchar(16) not null comment '振幅',
16             highest varchar(16) not null comment '最高',
17             lowest varchar(16) not null comment '最低',
18             today_begin varchar(16) not null comment '今开',
19             last_day varchar(16) not null comment '昨收'
20             
21 )'''
22 cursor.execute(sql)
23 db.close()
 1 conn = pymysql.connect(host="localhost", port=3306, user="root", passwd="999321", db="Stock", charset="utf8")
 2         cursor = conn.cursor()  # 获取游标
 3         try:
 4             print(count, num, name, value, Quote_change, Ups_and_downs, Volume, Turnover, amplitude, highest, lowest,today_begin, last_day)
 5             cursor.execute(
 6                 "insert into stocks(count,num,name,value,Quote_change,Ups_and_downs,Volume,Turnover,amplitude,highest,lowest,today_begin,last_day) values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)",
 7                 (count, num, name, value, Quote_change, Ups_and_downs, Volume, Turnover, amplitude, highest, lowest, today_begin, last_day))
 8         except Exception as err:
 9             print(err)
10         conn.commit()
11         conn.close()

⑦结果展示:

 

码云地址:https://gitee.com/shuai321/data-acquisition/blob/master/作业4/exe4.3.py

(3)心得体会:

第三题是对selenium知识的综合应用,可能是刚学还没有实践练习很多,所以这道题耗费了很多的时间,主要存在的问题就是在时间等待上面,因为要等待页面加载,所以必须加上时间等待才可以。关于信息定位上问题不是很大,因为之前有爬取过这个股票网站,而且XPath相对简单,通过position()就可以定位到每一个我们需要的。最后是存储到MySQL,经过许多实践对于存储没有问题了,后续还需要加强对selenium的练习,尤其是控制点击按钮,翻页,以及登录等等!

 

posted @ 2021-11-14 00:30  哈哈哈GS  阅读(37)  评论(0编辑  收藏  举报