数据采集第五次作业
作业一:
(1)实验要求:
• 要求: 熟练掌握 Selenium 查找HTML元素、爬取Ajax网页数据、等待HTML元素等内容。 使用Selenium框架爬取京东商城某类商品信息及图片。
• 候选网站:http://www.jd.com/
• 关键词:学生自由选择
• 输出信息:MYSQL的输出信息如下
mNo | mMark | mPrice | mNote | mFile |
000001 |
三星 Galaxy |
9199.00 |
三星Galaxy Note20 Ultra 5G... |
000001.jpg |
(2)题目分析:
①首先打开网站源代码,我们要找到搜索框、商品的信息以及所在列表、还有就是控制翻页的按钮:
用来定位搜索框:
用来定位商品列表:
用来定位商品信息,下图分别为图片、价格、名称和简介、翻页:
②代码部分:
1 from selenium import webdriver
2 from selenium.webdriver.chrome.options import Options
3 import urllib.request
4 import threading
5 import sqlite3
6 import os
7 import datetime
8 from selenium.webdriver.common.by import By
9 from selenium.webdriver.common.keys import Keys
10 import time
11
12 class MySpider:
13 headers = {
14 "User-Agent": "SMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
15 "Chrome/86.0.4240.183 Safari/537.361 "
16 }
17 # 保存图片的文件夹
18 imagePath = "imgs/dangdang"
19 def startUp(self, url, key):
20 # Initializing Chrome browser
21 chrome_options = Options()
22 chrome_options.add_argument('--headless')
23 chrome_options.add_argument('--disable-gpu')
24 self.driver = webdriver.Chrome()
25 self.threads = []
26 self.No = 0
27 self.imgNo = 0
28 try:
29 self.con = sqlite3.connect("phones.db")
30 self.cursor = self.con.cursor()
31 try:
32 # 如果有表就删除
33 self.cursor.execute("drop table phones")
34 except:
35 pass
36 try:
37 # 建立新的表
38 sql = "create table phones (mNo varchar(32) primary key, mMark varchar(256),mPrice varchar(32),mNote varchar(1024),mFile varchar(256))"
39 self.cursor.execute(sql)
40 except:
41 pass
42 except Exception as err:
43 print(err)
44 # Initializing images folder
45 try:
46 if not os.path.exists(MySpider.imagePath):
47 os.mkdir(MySpider.imagePath)
48 images = os.listdir(MySpider.imagePath)
49 for img in images:
50 s = os.path.join(MySpider.imagePath, img)
51 os.remove(s)
52 except Exception as err:
53 print(err)
54 self.driver.get(url)
55 keyInput = self.driver.find_element(By.ID,"key")
56 keyInput.send_keys(key)
57 keyInput.send_keys(Keys.ENTER)
58
59 def closeUp(self):
60 try:
61 self.con.commit()
62 self.con.close()
63 self.driver.close()
64 except Exception as err:
65 print(err)
66 def insertDB(self, mNo, mMark, mPrice, mNote, mFile):
67 try:
68 sql = "insert into phones (mNo,mMark,mPrice,mNote,mFile) values (?,?,?,?,?)"
69 self.cursor.execute(sql, (mNo, mMark, mPrice, mNote, mFile))
70 except Exception as err:
71 print(err)
72
73 def showDB(self):
74 try:
75 con = sqlite3.connect("phones.db")
76 cursor = con.cursor()
77 print("%-8s%-16s%-8s%-16s%s" % ("No", "Mark", "Price", "Image", "Note"))
78 cursor.execute("select mNo,mMark,mPrice,mFile,mNote from phones order by mNo")
79 rows = cursor.fetchall()
80 for row in rows:
81 print("%-8s %-16s %-8s %-16s %s" % (row[0], row[1], row[2], row[3], row[4]))
82 con.close()
83 except Exception as err:
84 print(err)
85
86 def download(self, src1, src2, mFile):
87 data = None
88 if src1:
89 try:
90 req = urllib.request.Request(src1, headers=MySpider.headers)
91 resp = urllib.request.urlopen(req, timeout=10)
92 data = resp.read()
93 except:
94 pass
95 if not data and src2:
96 try:
97 req = urllib.request.Request(src2, headers=MySpider.headers)
98 resp = urllib.request.urlopen(req, timeout=10)
99 data = resp.read()
100 except:
101 pass
102 if data:
103 print("download begin", mFile)
104 fobj = open(MySpider.imagePath + "\\" + mFile, "wb")
105 fobj.write(data)
106 fobj.close()
107 print("download finish", mFile)
108 def processSpider(self):
109 try:
110 time.sleep(1)
111 print(self.driver.current_url)
112 lis = self.driver.find_elements(By.XPATH,"//div[@id='J_goodsList']//li[@class='gl-item']")
113 for li in lis:
114 try:
115 src1 = li.find_element(By.XPATH,".//div[@class='p-img']//a//img").get_attribute("src")
116 except:
117 src1 = ""
118 try:
119 src2 = li.find_element(By.XPATH,".//div[@class='p-img']//a//img").get_attribute("data-lazy-img")
120 except:
121 src2 = ""
122 try:
123 price = li.find_element(By.XPATH,".//div[@class='p-price']//i").text
124 except:
125 price = "0"
126 try:
127 note = li.find_element(By.XPATH,".//div[@class='p-name p-name-type-2']//a//em").text
128 mark = note.split(" ")[0]
129 mark = mark.replace("爱心东东\n", "")
130 mark = mark.replace(",", "")
131 note = note.replace("爱心东东\n", "")
132 note = note.replace(",", "")
133
134 except:
135 note = ""
136 mark = ""
137 src2 = ""
138 self.No = self.No + 1
139 no = str(self.No)
140 while len(no) < 6:
141 no = "0" + no
142 print(no, mark, price)
143 if src1:
144 src1 = urllib.request.urljoin(self.driver.current_url, src1)
145 p = src1.rfind(".")
146 mFile = no + src1[p:]
147 elif src2:
148 src2 = urllib.request.urljoin(self.driver.current_url, src2)
149 p = src2.rfind(".")
150 mFile = no + src2[p:]
151 if src1 or src2:
152 T = threading.Thread(target=self.download, args=(src1, src2, mFile))
153 T.setDaemon(False)
154 T.start()
155 self.threads.append(T)
156 else:
157 mFile = ""
158 self.insertDB(no, mark, price, note, mFile)
159 try:
160 self.driver.find_element(By.XPATH,"//span[@class='p-num']//a[@class='pn-prev disabled']")
161 except:
162 nextPage = self.driver.find_elements(By.XPATH,"//span[@class='p-num']//a[@class='pn-next']")
163 time.sleep(10)
164 nextPage.click()
165 self.processSpider()
166 except Exception as err:
167 print(err)
168
169 def executeSpider(self, url, key):
170 starttime = datetime.datetime.now()
171 print("Spider starting......")
172 self.startUp(url, key)
173 print("Spider processing......")
174 self.processSpider()
175 print("Spider closing......")
176 self.closeUp()
177 for t in self.threads:
178 t.join()
179 print("Spider completed......")
180 endtime = datetime.datetime.now()
181 elapsed = (endtime - starttime).seconds
182 print("Total ", elapsed, " seconds elapsed")
183 url = "http://www.jd.com"
184 spider = MySpider()
185 while True:
186 print("1.爬取")
187 print("2.显示")
188 print("3.退出")
189 s = input("请选择(1,2,3):")
190 if s == "1":
191 spider.executeSpider(url, "手机")
192 continue
193 elif s == "2":
194 spider.showDB()
195 continue
196 elif s == "3":
197 break
③结果展示:
控制台输出:
数据库存储:
本地文件夹查看:
码云地址:https://gitee.com/shuai321/data-acquisition/blob/master/作业5/exe5.1.py
(3)心得体会:
第一题是对老师上课讲的一个例子的复现,通过自己亲自实践对selenium的框架以及使用更加熟悉,对selenium查找HTML
元素也做了巩固。但在其中也遇到了一个问题就是在运行完一次后,如果想再次运行就会出错,查看爬取内容时会提示数据库已经锁了,然后我就只能把之前的那张表删掉,然后重新运行建表。后来经过上网查阅发现可能是数据库的活跃状态发生改变。后续还要加强学习!
作业二:
(1)实验要求:
• 要求:
Δ熟练掌握 Selenium 查找HTML元素、实现用户模拟登录、爬取Ajax网页数据、等待 HTML元素等内容。
Δ使用Selenium框架+MySQL爬取中国mooc网课程资源信息(课程号、课程名称、教学 进度、课程状态,课程图片地址),同时存储图片到本地项目根目录下的imgs文件夹 中,图片的名称用课程名来存储。
• 候选网站:中国mooc网:https://www.icourse163.org
• 输出信息:MYSQL数据库存储和输出格式 表头应是英文命名例如:课程号ID,课程名称:cCourse……,由同学们自行定义
设计表头:
Id | cCourse | cCollege | cSchedule | cCourseStatus | cImgUrl |
1 |
Python网 络爬虫与 信息提取 |
北京理工 大学 | 已学3/18 课时 | 2021年5月18日 已结束 |
http://edu-i mage.nosd n.127.net/C 0AB6FA791 150F0DFC0 946B9A01C 8CB2.jpg |
2 |
........ |
(2)题目分析:
①由于这道题要求我们登录自己的账号爬取课程,所以要先通过查看网页源代码编写登录函数:
找到了登录的位置点击,然后选择其他方式登录
选择手机号登录:
找到输入框,输入账号(手机号)、密码,通过send_keys方发:
找到登录按钮,点击即可进入:
编写登录函数:
1 def Load_in():
2 time.sleep(1)
3 user = driver.find_element(By.XPATH,'//*[@id="j-topnav"]/div') # 点击登录
4 user.click()
5 time.sleep(1)
6 way = driver.find_element(By.XPATH,'//div[@class="ux-login-set-scan-code_ft"]/span') # 选择其他方式登录
7 way.click()
8 time.sleep(1)
9 telephone = driver.find_element(By.XPATH,'//ul[@class="ux-tabs-underline_hd"]/li[2]') # 选择电话号码登录
10 telephone.click()
11 time.sleep(1)
12 temp_iframe_id = driver.find_elements(By.TAG_NAME,'iframe')[1].get_attribute('id') #切换至页面弹窗
13 driver.switch_to.frame(temp_iframe_id)
14 driver.find_element(By.XPATH,'//input[@type="tel"]').send_keys('15135075590') #输入账号
15 time.sleep(1)
16 driver.find_element(By.XPATH,'//input[@class="j-inputtext dlemail"]').send_keys('******') #输入密码
17 time.sleep(1)
18 load_in = driver.find_element(By.XPATH,'//*[@id="submitBtn"]') #点击登录
19 load_in.click()
②因为要爬取的课程信息在我的课程中,所以点击进入个人中心:
编写进入个人中心函数:
1 def go_in():
2 time.sleep(2)
3 go_in = driver.find_element(By.XPATH,'//*[@id="j-indexNav-bar"]/div/div/div/div/div[7]/div[3]/div') # 进入个人中心
4 go_in.click()
5 spider()
③通过查看网页源代码发现,每一个课程的信息都在下图所示的红色方框的标签中:
图片URL在下图位置:
课程的其他需要的信息均在下图所示的标签中:
编写爬虫函数:
1 def spider():
2 global id
3 time.sleep(3)
4 divs = driver.find_elements(By.XPATH,'//*[@id="j-coursewrap"]/div/div[1]/div') #课程列表
5 print(len(divs))
6 for i in range(len(divs)):
7 div = divs[i]
8 course = div.find_element(By.XPATH,'./div/a/div[2]/div/div/div/span[2]').text #课程名
9 collage = div.find_element(By.XPATH,'./div/a/div[2]/div/div[2]/a').text #开设学校
10 schedule = div.find_element(By.XPATH,'./div[1]/a/div[2]/div[2]/div[1]/div[1]/div[1]/a/span').text #教学计划
11 coursestatus = div.find_element(By.XPATH,'./div[1]/a/div[2]/div[2]/div[2]').text #课程状态
12 imgurl = div.find_element(By.XPATH,'./div[1]/a/div[1]/img').get_attribute('src') #图片url
13 T = threading.Thread(target=download, args=(imgurl, id + 1)) # 创建进程
14 T.start()
15 threads.append(T)
16 id+=1
17 print(id)
18 print(course)
19 print(collage)
20 print(schedule)
21 print(coursestatus)
22 print(imgurl)
23 cursor.execute("insert into mooc(id, course, collage, schedule, coursestatus, imgurl) "
24 "values( % s, % s, % s, % s, % s, % s)",
25 (id, course, collage, schedule, coursestatus, imgurl))
④保存图片函数:
1 def download(img,no):
2 with open('./imgs' + str(no) + '.jpg', 'wb') as imgs:
3 pic = requests.get(img).content
4 imgs.write(pic)
⑤模拟浏览器:
1 url = 'https://www.icourse163.org/'
2 chrome_options = Options()
3 chrome_options.add_argument('--headless')
4 chrome_options.add_argument('--disable-gpu')
5 driver = webdriver.Chrome(options=chrome_options)
6 driver.get(url)
7 driver.maximize_window() #窗口最大化
⑥存入数据库:
1 # 连接数据库
2 con = pymysql.connect(host='localhost', port=3306, user='root', passwd='******', db='MOOC', charset='utf8')
3 cursor = con.cursor(pymysql.cursors.DictCursor)
4 sql = 'create table mooc(id int,course varchar(32),collage varchar(16),schedule varchar(32),coursestatus varchar(64),' \
5 'imgurl varchar(256));'
6 cursor.execute(sql)
7 cursor.execute("delete from mooc")
⑦结果展示:
控制台输出:
数据库展示:
本地文件展示:
码云地址:https://gitee.com/shuai321/data-acquisition/blob/master/作业5/exe5.2.py
(3)心得体会:
这一题是对selenium的综合应用,包括了查找HTML元素、实现用户模拟登录、爬取Ajax网页数据、等待 HTML元素等内容,总体来说难度较大,做了很久,中途还遇到了一个问题就是在编写爬虫程序时,一直显示爬取的内容为空,检查了XPath语句也没有出错,后来是发现在进入课程中心函数和爬虫程序之间没有设置等待时间,导致页面信息还没有加载出来,才出现爬取内容为空的情况。后续就是考试了,还要多加巩固练习,更加熟练使用selenium!
作业三:
(1)实验要求:
• 要求: 理解Flume架构和关键特性,掌握使用Flume完成日志采集任务。 完成Flume日志采集实验,包含以下步骤:
任务一:开通MapReduce服务
任务二:Python脚本生成测试数据
任务三:配置Kafka
任务四:安装Flume客户端
任务五:配置Flume采集数据
(2)实验步骤:
任务一:开通MapReduce服务。(开通步骤较多,不截图展示)
任务二:Python脚本生成测试数据
①编写Python脚本,使用Xshell 7连接服务器:
②进入/opt/client/目录,使用vi命令编写Python脚本:vi autodatapython.py(这里直接使用xftp7将本地的autodatapython.py文件上传至服务器/opt/client/目录下即可):
③使用mkdir命令在/tmp下创建目录flume_spooldir,我们把Python脚本模拟生成的数据放到此目录下,后面Flume就监控这个文件下的目录,以读取数据。执行Python命令,测试生成100条数据,然后查看数据:
任务三:配置Kafka:
①首先设置环境变量,执行source命令,使变量生效:
②在kafka中创建topic,查看topic信息:
任务四:安装Flume客户端:
①下载完成后会有弹出框提示下载到哪一台服务器上(这台机器就是Master节点),路径就是/tmp/MRS-client:
② 解压下载的flume客户端文件:
③解压“MRS_Flume_ClientConfig.tar”文件:
④ 安装Flume环境变量:
⑤解压Flume客户端:
⑥ 安装Flume客户端:
⑦ 重启Flume服务:
任务五:配置Flume采集数据:
①修改配置文件(注意更换为自己Kafka的ip,端口号一般不动):
② 创建消费者消费kafka中的数据:
(3)实验心得:
学会了如何使用Flume进行实时流前端数据采集,理解了Flume架构和关键特性,掌握了如何使用Flume完成日志采集任务。
遇到的问题:在任务五配置文件时,使用xftp直接上传了编辑好的文件,然后出错了,原因是在原来的conf文件夹中有一个空的properties文件了。删掉后就解决了。