数据采集第三次大作业
第三次大作业
作业1
1.1实验题目
-
要求:指定一个网站,爬取这个网站中的所有的所有图片,例如中国气象网(http://www.weather.com.cn)。分别使用单线程和多线程的方式爬取。(限定爬取图片数量为学号后3位)
-
输出信息:
将下载的Url信息在控制台输出,并将下载的图片存储在images子文件夹中,并给出截图。
1.2单线程编写思路
1.2.1获取天气网主页的所有链接
因为想要实现翻页,所以开始考虑从不同地区的天气页面来进行翻页,但是得到每个地区的编号进行翻页十分麻烦,同时存在许多相同图片。
所以最后考虑从主页获得其他页面链接,从中得到图片
start_url = "http://www.weather.com.cn/"
data = getHTMLText(start_url)
html=etree.HTML(data)
#找到主页下所有a中的href属性
urlli = html.xpath("//a/@href")
因为得到的urlli
中存在不是其他页面的链接,比如:
所以,使用以下代码进行筛选:
urls=[]
for url in urlli:
if(url[0:7]=="http://"):
urls.append(url)
1.2.2从链接中得到图片链接
提取每个链接中的图片链接,然后除去相同的链接,每次出现一个新的图片链接就调用下载图片的方法对图片进行下载。
images = soup.select("img")
for image in images:
try:
src = image["src"]
url = urllib.request.urljoin(start_url,src)
if url not in urls:
count += 1
if count>15:
break
urls.append(url)
print(url)
download(url,count)
except Exception as err:
print(err)
1.2.3图片下载
file_name = url.split('/')[-1]
rep = requests.get(url)
with open("images\\"+ file_name, 'wb') as f:
f.write(rep.content)
f.close()
print("downloaded " + file_name )
1.2.4结果
控制台输出图片链接以及下载成功的提醒。
本地文件夹images下的结果。
1.3多线程编写思路
1.3.1多线程与单线程区别
主要在于要存在子进程,所以使用threads = []
来存储进程,以及使用部分,代码如下:
T = threading.Thread(target=download, args=(url,))
T.setDaemon(False)
T.start()
threads.append(T)
其余部分与单线程一致。
1.3.2 结果
控制台输出图片链接以及下载成功的提醒。
本地文件夹images下的结果。
1.4完整代码
https://gitee.com/q_kj/crawl_project/tree/master/third
1.5小结
这题开始困扰我的主要在于如何进行翻页,如果对地区天气界面进行翻页太过于复杂,所以最后从主界面中提取其他页面链接进行爬取。其他部分参考课上的代码进行修改便可。
作业2
2.1实验题目
-
要求:使用scrapy框架复现作业①。
-
输出信息:
同作业1
2.2思路
2.2.1 items.py
class WeatherItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
imag = scrapy.Field()
imag用于存储图片的链接。
2.2.2MySpider.py
parse
函数主要用于获得主页面所有其他页面的链接。
urls=[]
#先找到主页上所有的a标签下的herf属性
urllib = response.xpath("//a/@href").extract()
for url in urllib:
#因为有些herf属性的结果不是链接,所以进行筛选,结果存入urls
if (url[0:7] == "http://"):
if url not in urls:
urls.append(url)
#对每个链接调用图片爬取的函数
for url in urls:
if self.count<135:
yield scrapy.Request(url=url,callback=self.imageSpider)
imageSpider
函数主要用于获得页面所有图片的链接。
imgurl=[]
#提取每个img标签中的src属性中的图片链接
img_url = reponse.xpath("//img//@src").extract()
#if self.count>=135:
#return
for url in img_url:
#不确定每个都是否是链接,就进行了筛选
if (url[0:7] == "http://"):
#排除重复的标签
if url not in imgurl:
self.count += 1
#如果图片大于135,就不行添加
f self.count < 135:
imgurl.append(url)
for url in imgurl:
item = WeatherItem()
item["imag"] = url
yield item
2.2.3 pipelines.py
开启spideropen_spider
:
def open_spider(self,spider):
print("opened")
self.opened=True
self.count=0
关闭spiderclose_spider
:
def close_spider(self,spider):
if self.opened:
self.opened=False
print("closed")
print("总共爬取",self.count,"张图片")
上诉部分是对老师所给ppt中的代码进行改写后的。
process_item
实现图片的下载:
self.count = self.count + 1
img=item["imag"]
print(img)
#if self.count>135:
#self.close_spider()
if self.opened:
try:
#将图片下载到本地文件夹中
rep = requests.get(img)
file_name = img.split('/')[-1]
with open("images\\" + file_name, 'wb') as f:
f.write(rep.content)
f.close()
print("downloaded " + file_name)
2.2.4结果
控制台信息:
images文件夹下结果:
2.3完整代码
https://gitee.com/q_kj/crawl_project/tree/master/weather
2.4小结
第二题和第一题十分相似,第二题主要在于scrapy框架中的各个文件的编写。
作业3
3.1实验题目
-
要求:爬取豆瓣电影数据使用scrapy和xpath,并将内容存储到数据库,同时将图片存储在
imgs路径下。
-
输出信息:
序号 电影名称 导演 演员 简介 电影评分 电影封面 1 肖申克的救赎 弗兰克·德拉邦特 蒂姆·罗宾斯 希望让人自由 9.7 ./imgs/xsk.jpg 2....
3.2思路
3.2.1 item.py
class DoubanItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
rank = scrapy.Field()
movie_name = scrapy.Field()
director = scrapy.Field()
actors = scrapy.Field()
brief_introduction = scrapy.Field()
grade = scrapy.Field()
imag = scrapy.Field()
3.2.2 spider.py
通过xpath
提取各个部分的内容:
rank = response.xpath("//div[@class='pic']/em/text()").extract() #排名
name = response.xpath("//div[@class='hd']/a/span[1]/text()").extract() #电影名字
dir_acts = response.xpath("//div[@class='bd']/p[1]/text()").extract() #因为导演和演员信息混在一起,所以需要再次提取
brief_intro = response.xpath("//div[@class='bd']/p[2]/span/text()").extract() #简介
grade = response.xpath("//div[@class='bd']/div[@class='star']/span[@class='rating_num']/text()").extract() #评分
img = response.xpath("//div[@class='pic']/a/img/@src").extract() #电影封面图片链接
然后问题在于通过上面得到的导演和主演的信息混在一起,同时还有其他信息,如下图:
所以需要再次对其进行提取:
dname = [] #用来存导演名
aname = [] #用来存主演名
count = 0 #用于后面区分dir_acts中的奇偶
#发现每一个电影的dir_act都窜在两个部分,第一部分是导演和主演,第二部分是地区和日期等
#所以考虑提取dir_acts中的偶数部分,即导演和主演
for dir_act in dir_acts:
count += 1
if (count % 2 != 0):
#导演和主演之间存在"\xa0\xa0\xa0",所以以此分割成两部分
dir_act = dir_act.strip().split('\xa0\xa0\xa0')
#提取出的第一部分去除”导演:“,存入dname中
dname.append(dir_act[0].split('导演:')[1])
# 提取出的第二部分去除”主演:“,存入aname中
aname.append(dir_act[1].split('主演:')[1])
elif (count % 2 == 0):
continue
然后将最终结果存入item中:
item = DoubanItem()
item["rank"] = int(rank[i])
item["movie_name"] = name[i]
item["director"] = dname[i]
item["actors"] = aname[i]
item["brief_introduction"] = brief_intro[i]
item["grade"]=grade[i]
item["imag"] = img[i]
yield item
最后在于翻页:
#实现翻页,https://movie.douban.com/top250?start=(?)&filter=,?中正好是25的倍数,以此实现翻页
url_f="https://movie.douban.com/top250"
for i in range(1,10):
url=url_f+"?start="+str(i*25)+"&filter="
#得到下一页的url,回调parse,继续上面的操作
yield scrapy.Request(url=url,callback=self.parse)
3.2.3pipelines.py
open_spider
:打开spider,同时创建数据库和表。
def open_spider(self,spider):
print("opened")
try:
#与数据库进行连接,创建douban数据库
self.con = sqlite3.connect("douban.db")
self.cursor = self.con.cursor()
#创建表
self.cursor.execute("create table douban(排名 int(4),电影名 varchar(25),导演 varchar(30),主演 varchar(70),简介 varchar(70),评分 varchar(8),封面 varchar(80))")
self.opened = True
except Exception as err:
print(err)
self.opened=False
close_spider
:用于关闭spider。
def close_spider(self,spider):
if self.opened:
self.con.commit()
self.con.close()
self.opened=False
process_item
:用于插入数据和下载图片。
#向表中插入item中的数据
self.cursor.execute("insert into douban(排名,电影名,导演,主演,简介,评分,封面)values(?,?,?,?,?,?,?)",(item['rank'],item['movie_name'],item['director'],item['actors'],item['brief_introduction'],item['grade'],item['imag']))
#将电影封面存入本地文件夹中
rep = requests.get(img)
print(img)
#将封面名设为电影名
file_name = item['movie_name']
with open("images\\" + file_name+".jpg", 'wb') as f:
f.write(rep.content)
f.close()
print("downloaded " + file_name)
3.2.4结果
控制台信息:
数据库结果:
images本地文件夹照片结果:
3.3完整代码
https://gitee.com/q_kj/crawl_project/tree/master/douban
3.4小结
因为之前代码一直爬取不成功,所以多次爬取,最后提示检测到有异常请求从你的 IP 发出
,然后登陆豆瓣,虽然没有这个提醒,但又显示了Crawled (403) <GET https://movie.douban.com/top250> (referer: None)
,根据https://www.cnblogs.com/guanguan-com/p/13540188.html这个链接中的方法成功解决。所以在爬虫时一定要注意:先爬取部分页面内容,正确性测试,没有问题了,联网爬取 爬取要设时间等待,限制速度。