1、Python 爬虫项目教程爬虫项目教程(微课版)习题参考答案微课版)习题参考答案 练习 1 1 Flask 是一个比较简单的 Python Web 开发框架,你知道 Python 还有哪些比较流行的Web 开发框架吗?说说它们的主要区别。答:企业级开发框架Django 高并发处理框架Tornado 快速建站的框架Flask 底层自定义协议网络框架Twisted 2使用 GET 方法提交数据与使用 POST 方法提交数据有什么不同?在 Flask 中如何获取提交的数据?答:Flask 获取 GET/POST 数据:flask.request.values.get(参数名称,默认值)3使用 Fla
2、sk 编写一个 Web 程序,它接收如下代码提交的 user_name 与 user_pass数据。答:import flask app=flask.Flask(web)app.route(/)def index():s=return s 2 app.route(/login,methods=GET,POST)def login():user_name=flask.request.values.get(user_name,)user_pass=flask.request.values.get(user_pass,)return user_name+,+user_pass app.debug=T
3、rue app.run()4说出下面正则表达式匹配的字符串分别是什么。(1)rw+s(2)rw+b(3)rd+-d+(4)rw+(w+.)+w+(5)r(b|cd)ef 答:省略 5 使用正则表达式匹配 HTML 代码中所有形如的 JPG图像文件,找出一个网站中所有这样表示的 JPG 图像文件,并下载这些图像文件。答:import urllib.request import re def getHtml(url):html=try:resp=urllib.request.urlopen(url)data=resp.read()try:html=data.decode().lower()exce
4、pt:html=data.decode(gbk).lower()except Exception as err:print(err)return html def parseHtml(html):3 try:imgReg=r srcReg=rhttp:/.+.jpg while True:m=re.search(imgReg,html)if m:s=htmlm.start():m.end()n=re.search(srcReg,s)src=sn.start():n.end()download(src)html=htmlm.end():else:break except Exception as
5、 err:print(err)def download(src):try:print(downloding,src)resp=urllib.request.urlopen(src)data=resp.read()p=src.rfind(/)fn=srcp+1:fobj=open(fn,wb)fobj.write(data)fobj.close()print(downloaded,fn)except Exception as err:print(err)url=.html=getHtml(url)parseHtml(html)4 练习 2 1简单说明 Beautiful Soup 解析数据的特点
6、。答:省略 2用 Beautiful Soup 装载下面的 HTML 文档,并以规范的格式输出,比较与原来 HTML文档的区别,说明 Beautiful Soup 是如何修改的。Hi Hello End 答:from bs4 import BeautifulSoup html=Hi Hello End soup=BeautifulSoup(html,html.parser)print(soup.prettify()3重新编写本书项目 1 中爬取外汇网站数据的程序,使用 Beautiful Soup 分解出中的数据。答:import urllib.request from bs4 import
7、BeautifulSoup import sqlite3 class MySpider:def openDB(self):#初始化数据库,创建数据库 rates.db 与一张空表 rates self.con=sqlite3.connect(rates.db)self.cursor=self.con.cursor()try:self.cursor.execute(drop table rates)except:pass 5 sql=create table rates(Currency varchar(256)primary key,TSP float,CSP float,TBP float,
8、CBP float,Time varchar(256)try:self.cursor.execute(sql)except:pass def closeDB(self):#关闭数据库 mit()self.con.close()def insertDB(self,Currency,TSP,CSP,TBP,CBP,Time):#记录插入数据库 try:sql=insert into rates(Currency,TSP,CSP,TBP,CBP,Time)values(?,?,?,?,?,?)self.cursor.execute(sql,Currency,TSP,CSP,TBP,CBP,Time)
9、except Exception as err:print(err)def show(self):#显示函数 self.cursor.execute(select Currency,TSP,CSP,TBP,CBP,Time from rates)rows=self.cursor.fetchall()print(%-18s%-12s%-12s%-12s%-12s%-12s%(Currency,TSP,CSP,TBP,CBP,Time)for row in rows:print(%-18s%-12.2f%-12.2f%-12.2f%-12.2f%-12s%(row0,row1,row2,row3,
10、row4,row5)def spider(self,url):#爬虫函数 try:resp=urllib.request.urlopen(url)data=resp.read()html=data.decode()soup=BeautifulSoup(html,html.parser)div=soup.find(div,attrs=id:realRateInfo)6 trs=div.find_all(tr)for tr in trs1:tds=tr.find_all(td)Currency=tds0.text.strip()TSP=float(tds3.text)CSP=float(tds4.
11、text)TBP=float(tds5.text)CBP=float(tds6.text)Time=tds7.text.strip()self.insertDB(Currency,TSP,CSP,TBP,CBP,Time)except Exception as err:print(err)def process(self):#爬取过程 self.openDB()self.spider(http:/ spider=MySpider()spider.process()4下面是一段 HTML 代码:Harry Potter 23.99 学习 XML 39.95 Learning Python 30.
12、20 试用 Beautiful Soup 完成下面的任务。(1)找出所有书的名称。7 (2)找出所有英文书的名称与价格。(3)找出价格在 30 元以上的所有书的名称。答:from bs4 import BeautifulSoup html=Harry Potter 23.99 学习 XML 39.95 Learning Python 30.20 soup=BeautifulSoup(html,html.parser)books=soup.find_all(book)for b in books:print(b.find(title).text)print()books=soup.find_al
13、l(book)for b in books:title=b.find(title,attrs=lang:english)if title:print(title.text)print()for b in books:price=b.find(price).text if float(price)mVersion:python=ppython url=purl mVersion=s return python,url def searchPython(surl):resp=urllib.request.urlopen(surl)data=resp.read()html=data.decode()
14、soup=BeautifulSoup(html,lxml)div=soup.find(div,attrs=class:row download-list-widget)ol=div.find(name=ol,attrs=class:list-row-container menu)lis=ol.find_all(li)pList=for li in lis:a=li.find(name=span,attrs=class:release-number).find(a)python=a.text url=urllib.request.urljoin(surl,ahref)print(%-20s%s%
15、(python,url)pList.append(python:python,url:url)return pList try:pList=searchPython(https:/www.python.org/downloads/)python,url=getLatestVersion(pList)print(The latest version)print(python,url)except Exception as e:10 print(e)6在中国天气网中查找一个城市,如深圳,会转到地址为“http:/ 2-8-2 所示。图 2-8-2 深圳的天气预报 编写爬虫程序爬取该网站 7 天内的
16、天气预报,包括日期、天气、温度等数据。答:from bs4 import BeautifulSoup from bs4 import UnicodeDammit import urllib.request url=http:/ try:headers=User-Agent:Mozilla/5.0(Windows;U;Windows NT 6.0 x64;en-US;rv:1.9pre)Gecko/2008072421 Minefield/3.0.2pre req=urllib.request.Request(url,headers=headers)data=urllib.request.url
17、open(req)data=data.read()dammit=UnicodeDammit(data,utf-8,gbk)data=dammit.unicode_markup soup=BeautifulSoup(data,lxml)lis=soup.select(ulclass=t clearfix li)for li in lis:try:date=li.select(h1)0.text weather=li.select(pclass=wea)0.text 11 temp=li.select(pclass=tem span)0.text+/+li.select(pclass=tem i)
18、0.text print(date,weather,temp)except Exception as err:print(err)except Exception as err:print(err)12 练习 3 1什么是深度优先法和广度优先法,它们有什么特点?答:省略 2如何启动一个 Python 线程?为什么说爬虫程序一般都会使用多线程?答:省略 3设计两个网页 A.html 与 B.html,它们都包含相同结构的学生信息(姓名、性别、年龄)。A.html 文件与 B.html 文件如下。(1)A.html:姓名:A1性别:男年龄:20 姓名:A10性别:女年龄:18(2)B.html:姓
19、名:B1性别:男年龄:20 姓名:B10性别:女年龄:18 设计一个包含两个线程的爬虫程序,一个线程爬取 A.html,另外一个线程爬取 B.html,爬取的学生信息都保存到列表 students 中,最后显示爬取的结果。答:(1)server.py import flask app=flask.Flask(web)app.route(/A)def A():s=姓名:A1性别:男年龄:20 姓名:A10性别:女年龄:18 return s app.route(/B)def B():s=姓名:B1性别:男年龄:20 姓名:B10性别:女年龄:18 13 return s app.debug=Tr
20、ue app.run()(2)spider.py from bs4 import BeautifulSoup import urllib.request import threading lock=threading.RLock()def getValue(s):p=s.find(:)return sp+1:def getAB(page):global students try:resp=urllib.request.urlopen(http:/127.0.0.1:5000/+page)html=resp.read().decode()soup=BeautifulSoup(html,html.
21、parser)divs=soup.find_all(div)i=0 while ilen(divs):name=getValue(divsi.text)sex=getValue(divsi+1.text)age=getValue(divsi+2.text)i=i+3 lock.acquire()students.append(name,sex,age)lock.release()except Exception as err:print(err)students=TA=threading.Thread(target=getAB,args=A)TB=threading.Thread(target
22、=getAB,args=B)TA.start()TB.start()TA.join()TB.join()14 print(students)结果:B1,男,20,B10,女,18,A1,男,20,A10,女,18 4设计一个爬虫程序,爬取一个网站的所有图像。答:from bs4 import BeautifulSoup from bs4 import UnicodeDammit import urllib.request import os def imageSpider(start_url):try:urls=req=urllib.request.Request(start_url,head
23、ers=headers)data=urllib.request.urlopen(req)data=data.read()dammit=UnicodeDammit(data,utf-8,gbk)data=dammit.unicode_markup soup=BeautifulSoup(data,lxml)images=soup.select(img)for image in images:try:src=imagesrc url=urllib.request.urljoin(start_url,src)if url not in urls:urls.append(url)print(url)do
24、wnload(url)except Exception as err:print(err)except Exception as err:print(err)def download(url):global count try:count=count+1 if(urllen(url)-4=.):ext=urllen(url)-4:else:15 ext=req=urllib.request.Request(url,headers=headers)data=urllib.request.urlopen(req,timeout=100)data=data.read()fobj=open(image
25、s+str(count)+ext,wb)fobj.write(data)fobj.close()print(downloaded+str(count)+ext)except Exception as err:print(err)headers=User-Agent:Mozilla/5.0(Windows;U;Windows NT 6.0 x64;en-US;rv:1.9pre)Gecko/2008072421 Minefield/3.0.2pre count=0 if not os.path.exists(images):os.mkdir(images)start_url=http:/ ima
26、geSpider(start_url)16 练习 4 1简单说明 Scrapy 的入口地址的规定。答:省略 2比较使用 XPath 和 Beautiful Soup 解析 HTML 代码的特点与区别。答:省略 3在 Scrapy 中如何把爬取的数据写入数据库?items.py 与 pipelines.py 文件有什么作用?答:items.py 定义数据字段,pipelines.py 获取数据进行存储。4Python 中的 yield 语句如何工作?为什么 Scrapy 爬到的数据使用 yield 语句返回,而不是使用 return 语句返回?答:省略 5Scrapy 是如何实现爬取多个网页的数
27、据的?如何理解分布式爬取过程?答:省略 6有一个服务器程序,它根据请求页面的不同来展示 3 组学生信息,这些学生信息分别存储在 students1.txt、students2.txt、students3.txt 文件中,每个页面有相同的结构(学号No、姓名 Name、性别 Gender、年龄 Age),参数 page=N 控制展示 studentsN.txt 的学生表格(N=1,2,3),程序如下:import flask app=flask.Flask(_name_)app.route(/)def show():page=flask.request.args.get(page)if page
28、 in flask.request.args else 1 maxpage=3 page=int(page)st=学生信息表 st=st+fobj=open(students+str(page)+.txt,rt,encoding=utf-8)while True:#读取一行,去除行尾部“n”换行符号 s=fobj.readline().strip(n)#如果读到文件尾部就退出 if s=:17 break#按逗号拆分 s=s.split(,)st=st+#把各个数据组织在中 for i in range(len(s):st=st+si+#完成一行 st=st+fobj.close()st=st
29、+st=st+if page1:st=st+【前一页】if pagemaxpage:st=st+【下一页】st=st+st=st+st=st+Page:+str(page)+/+str(maxpage)+return st if _name_=_main_:app.run()执行服务器程序,学生信息如图 4-10-1 所示。图 4-10-1 学生信息 使用 Scrapy 设计一个爬虫程序,爬取所有学生的信息并将其存储到数据库中。答:1、server.py import flask app=flask.Flask(_name_)app.route(/)18 def show():page=fla
30、sk.request.args.get(page)if page in flask.request.args else 1 maxpage=3 page=int(page)st=学生信息表 st=st+fobj=open(students+str(page)+.txt,rt,encoding=utf-8)while True:#读取一行,去除行尾部“n”换行符号 s=fobj.readline().strip(n)#如果读到文件尾部就退出 if s=:break#按逗号拆分 s=s.split(,)st=st+#把各个数据组织在中 for i in range(len(s):st=st+si+
31、#完成一行 st=st+fobj.close()st=st+st=st+if page1:st=st+【前一页】if pagemaxpage:st=st+【下一页】st=st+st=st+st=st+Page:+str(page)+/+str(maxpage)+return st if _name_=_main_:app.debug=True app.run()2、爬虫程序 scrapy startproject demo(1)items.py 19 import scrapy class StudentItem(scrapy.Item):#define the fields for your
32、 item here like:No=scrapy.Field()Name=scrapy.Field()Gender=scrapy.Field()Age=scrapy.Field()(2)pipelines.py import sqlite3 class DemoPipeline:def open_spider(self,spider):print(opened)try:self.con=sqlite3.connect(students.db)self.cursor=self.con.cursor()try:self.cursor.execute(drop table students)exc
33、ept:pass try:sql=create table students(No varchar(8)primary key,Name varchar(32),Gender varchar(8),Age int)self.cursor.execute(sql)except:self.cursor.execute(delete from students)self.opened=True self.count=0 except Exception as err:print(err)self.opened=False def close_spider(self,spider):if self.o
34、pened:mit()20 self.con.close()self.opened=False print(closed)print(总共爬取,self.count,条记录)def process_item(self,item,spider):if self.opened:try:sql=insert into students(No,Name,Gender,Age)values(?,?,?,?)self.cursor.execute(sql,itemNo,itemName,itemGender,itemAge)self.count=self.count+1 except Exception
35、as err:print(err)return item (3)mySpider.py import scrapy from bs4 import BeautifulSoup from items import StudentItem class MySpider(scrapy.Spider):name=mySpider def start_requests(self):url=http:/127.0.0.1:5000 yield scrapy.Request(url=url,callback=self.parse)def parse(self,response):print(response
36、.url)html=response.body.decode()soup=BeautifulSoup(html,html.parser)trs=soup.find_all(tr)for tr in trs:tds=tr.find_all(td)item=StudentItem()itemNo=tds0.text itemName=tds1.text itemGender=tds2.text itemAge=int(tds3.text)21 yield item links=soup.find(div).find_all(a)nextLink=for link in links:if link.
37、text=【下一页】:nextLink=response.urljoin(linkhref)yield scrapy.Request(url=nextLink,callback=self.parse)break (4)settings.py BOT_NAME=demo SPIDER_MODULES=demo.spiders NEWSPIDER_MODULE=demo.spiders#Obey robots.txt rules ROBOTSTXT_OBEY=True#Configure item pipelines#See https:/docs.scrapy.org/en/latest/top
38、ics/item-pipeline.html ITEM_PIPELINES=demo.pipelines.DemoPipeline:300,22 练习 5 1说明 Selenium 的工作原理。为什么其能执行网页中的 JavaScript 程序?答:省略 2说明 Selenium 的等待方式。各种等待方式有什么特点?答:省略 3启动如下的服务器程序。import flask app=flask.Flask(_name_)app.route(/)def index():s=document.getElementById(jMsg).innerHTML=javascript 信息;return s
39、 app.run()(1)用 urllib 编写程序来获取网站的 HTML 代码。(2)用 Selenium 编写程序来获取网站的 HTML 代码。通过这两种方法获取的 HTML 代码是否相同?为什么?答:from bs4 import BeautifulSoup import urllib.request from selenium import webdriver from selenium.webdriver.chrome.options import Options def testSelenium():try:chrome_options=Options()chrome_option
40、s.add_argument(-headless)chrome_options.add_argument(-disable-gpu)driver=webdriver.Chrome(chrome_options=chrome_options)driver.get(http:/127.0.0.1:5000)html=driver.page_source soup=BeautifulSoup(html,lxml)jMsg=soup.find(span,attrs=id:jMsg)if jMsg:23 print(Selenium found,jMsg.text)else:print(Selenium
41、 not found)driver.close()except Exception as err:print(err)def testRequest():try:resp=urllib.request.urlopen(http:/127.0.0.1:5000)html=resp.read().decode()soup=BeautifulSoup(html,lxml)jMsg=soup.find(span,attrs=id:jMsg)if jMsg:print(Request found,jMsg.text)else:print(Request not found)except Exceptio
42、n as err:print(err)testRequest()testSelenium()结果:Request found Selenium found javascript 信息 4启动如下的服务器程序。import flask app=flask.Flask(_name_)app.route(/)def index():s=function msg()document.getElementById(jMsg).innerHTML=javascript 信息;window.setTimeout(msg,1000);return s app.run()24 试用 Selenium 编写爬虫程
43、序等待中出现的字符串,并爬取该字符串。答:from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from mon.by import By def testSelenium():try:chrome_options=Options()ch
44、rome_options.add_argument(-headless)chrome_options.add_argument(-disable-gpu)driver=webdriver.Chrome(chrome_options=chrome_options)driver.get(http:/127.0.0.1:5000)locator=(By.ID,jMsg)WebDriverWait(driver,10,0.5).until(EC.text_to_be_present_in_element(locator,java)msg=driver.find_element_by_id(jMsg).
45、text print(Selenium found,msg)driver.close()except Exception as err:print(err)testSelenium()5启动如下的服务器程序。import flask app=flask.Flask(_name_)app.route(/)def index():s=姓名 性别男女 return s 25 app.route(/handin)def handin():name=flask.request.values.get(name)gender=flask.request.values.get(gender)return+na
46、me+gender+app.run()试用 Selenium 编写程序:(1)填写姓名和性别为“张三”与“女”,并提交;(2)爬取提交后的姓名与性别。答:from selenium import webdriver from selenium.webdriver.chrome.options import Options import time def testSelenium():try:chrome_options=Options()chrome_options.add_argument(-headless)chrome_options.add_argument(-disable-gpu)
47、driver=webdriver.Chrome(chrome_options=chrome_options)#driver=webdriver.Chrome()driver.get(http:/127.0.0.1:5000)nameElem=driver.find_element_by_css_selector(inputname=name)genderElem=driver.find_element_by_css_selector(inputname=gendervalue=女)submitElem=driver.find_element_by_css_selector(inputtype=
48、submit)nameElem.send_keys(张三)genderElem.click()submitElem.click()time.sleep(1)name=driver.find_element_by_id(name).text gender=driver.find_element_by_id(gender).text print(name,gender)except Exception as err:print(err)testSelenium()26 27 练习 6 1AWS 的 DynamoDB 数据库与常用的其他数据库(如 MySQL、SQLite)相比有什么特点?答:Dyn
49、amoDB 是 NoSql 数据库,MySql、Sqlite 是 Sql 关系数据库。2如何理解 DynamoDB 数据库的数据项目,它与一般关系数据库的表格记录相比有什么不同?答:省略 3一组学生的选课情况如表 6-7-1 所示。表 6-7-1 选课情况 姓名(Name)课程(Course)A Python、Java、MySQL B Python C 暂缺 完成下列任务。(1)建立 DynamoDB 表格 courses 存储这组学生的选课情况,课程用列表表示。(2)修改 B 同学的课程为“Java、JavaScript”,C 同学的课程为“MySQL”。(3)查找所有选修“Java”课程的
50、同学。(4)如果已知 Python、Java、MySQL、JavaScript 课程的学分分别是 3、4、2、3,修改每位同学的课程数据结构为字典,如将 A 同学的课程数据结构修改为:Python:3;Java:4;MySQL:2(5)统计每位同学的总学分。答:import boto3 import sys def readKeys():keys=try:f=open(accessKeys.csv,rt)rows=f.readlines()if len(rows)=2:28 s=rows1.strip(n)s=s.split(,)keys=keyID:s0,secretKey:s1 f.clo