資料採集與融合技術——實驗三
阿新 • • 發佈:2021-11-09
作業①
-
要求:指定一個網站,爬取這個網站中的所有的所有圖片,例如中國氣象網(http://www.weather.com.cn)。分別使用單執行緒和多執行緒的方式爬取。(限定爬取圖片數量為學號後3位)
-
輸出資訊:將下載的Url資訊在控制檯輸出,並將下載的圖片儲存在images子資料夾中,並給出截圖。
實現過程
- 單執行緒實現過程及程式碼連結:https://gitee.com/chenshuooooo/data-acquisition/blob/master/%E4%BD%9C%E4%B8%9A3/1%E5%8D%95%E7%BA%BF%E7%A8%8B.py
1.解析網頁
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='gb18030') # 改變標準輸出的預設編碼為漢字編碼 url='http://www.weather.com.cn/' header = 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36' html=requests.get(url,header) data=html.text count = 1 #print(data)
2.正則表示式的構建
s1='<img src=\"(.*?)[png,jpg]\"'#匹配圖片地址
s2='href=\"(.*?)\"'#匹配子網址
3.爬取該網頁下及子網頁的所有圖片下載連結
for tag in tags: tag = tag +'g' print('下載圖片的地址是:'+tag) urllib.request.urlretrieve(tag, '陳碩爬取的書包圖片' + str(count) + '.jpg') count+=1 if count>104: break lis = re.findall(s2,data) for li in lis: ht = requests.get(li) dt = ht.text img_ls = re.findall(s1,dt)#匹配子網址中的圖片地址 for img in img_ls: img = img +'g' print('下載圖片的地址是:' + img) urllib.request.urlretrieve(img, '陳碩爬取的書包圖片' + str(count) + '.jpg') count+=1 if count>104: break if count>104: break
4.輸出結果
5.爬取下載結果
- 多執行緒實現過程及程式碼連結:https://gitee.com/chenshuooooo/data-acquisition/blob/master/%E4%BD%9C%E4%B8%9A3/1%E5%A4%9A%E7%BA%BF%E7%A8%8B.py
1.將urllib.request.urlretrieve方法封裝為download方法,再使用threading進行併發處理。
def download(url,name): urllib.request.urlretrieve(url) for tag in tags: tag = tag +'g' print('下載圖片'+str(count)+'的地址是:'+tag) T = threading.Thread(target=download(tag, '陳碩爬取的書包圖片' + str(count) + '.jpg')) T.setDaemon(False) T.start() count+=1 if count>104: break lis = re.findall(s2,data) for li in lis: ht = requests.get(li) dt = ht.text img_ls = re.findall(s1,dt)#匹配子網址中的圖片地址 for img in img_ls: img = img +'g' print('下載圖片' + str(count) + '的地址是:' + tag) T = threading.Thread(target=download(img, '陳碩爬取的書包圖片' + str(count) + '.jpg')) T.setDaemon(False) T.start() count+=1
心得體會
- 複習了併發的使用,對併發有了更加深刻的瞭解。
- 複習了正則表示式的寫法
作業②
-
要求:使用scrapy框架復現作業①。
-
輸出資訊:同作業①
實現過程
程式碼實現:https://gitee.com/chenshuooooo/data-acquisition/tree/master/%E4%BD%9C%E4%B8%9A3/%E7%AC%AC%E4%BA%8C%E9%A2%98
1.編寫weather.py爬蟲主程式
# -*- coding:utf-8 -*-
import scrapy
from ..items import Exp3Item
#031904104 陳碩
class WeatherSpider(scrapy.Spider):
name = 'weather'
start_urls = ['http://p.weather.com.cn/txqg/index.shtml']
global count
count = 0 # 計數,爬取學號後三位104項後就停止
def get_urllist(self,response):
urls = response.xpath('//div[@class="tu"]/a/@href').extract()#匹配子網址
for url in urls:
if self.count>104:
break
yield scrapy.Request(url=url, callback=self.get_imgurl)
def get_imgurl(self, response):
global count
item = Exp3Item()
img_url=response.xpath('//div[@class="buttons"]/span/img/@src')
for i in img_url:
count+=1
url=i.extract()
if self.count<=104:
item['img_url']=url
yield item
pass
2.setting.py
將機器人協議改為False,設定儲存路徑,以及爬蟲優先順序
3.編寫pipelines.py檔案
import requests
class Exp3Pipeline:
def open_spider(self, spider):
self.num = 1
def process_item(self, item, spider):
url = item['img_url']
resp = requests.get(url)
img = resp.content
with open('D:\image\%d' % (self.num) + '.jpg', 'wb') as f:
f.write(img)
print('%d' % (self.num))
self.num += 1
return item
4.編寫item.py
import scrapy
class Exp3Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
img_url = scrapy.Field() #圖片url地址
pass
5.編寫run.py,模擬命令列執行爬蟲
# -*- coding:utf-8 -*-
from scrapy import cmdline
import sys
sys.path.append(r'D:\python project\exp3\exp3spiders\weather')#新增爬蟲路徑,防止報錯找不到路徑
cmdline.execute('scrapy crawl weather'.split())#執行爬蟲
6.爬取結果
- 報錯: ERROR: Spider error processing <GET http://p.weather.com.cn/txqg/index.shtml> (referer: None)
通過查詢資料,發現可能是兩個方面的問題: - ①.xpath表示式解析錯誤(會導致爬蟲解析dom失敗),在詢問過大佬後,我重構了表示式,這方面應該沒問題
- ② 機器人協議為設定為False,在檢查過setting檔案後,發現已經修改,應該不是這個問題。
但是這兩個問題都解決後,還是報錯。
心得體會
- 複習了scrapy的使用,對scrapy有了一個更深的瞭解,確切感受到scrapy爬取速度確實比較快。
作業③
要求:爬取豆瓣電影資料使用scrapy和xpath,並將內容儲存到資料庫,同時將圖片儲存在imgs路徑下。
候選網站: https://movie.douban.com/top250
輸出資訊:
序號 | 電影名稱 | 導演 | 演員 | 簡介 | 電影評分 | 電影封面 |
---|---|---|---|---|---|---|
1 | 肖申克的救贖 | 弗蘭克·德拉邦特 | 蒂姆·羅賓斯 | 希望讓人自由 | 9.7 | ./imgs/xsk.jpg |
實現過程
程式碼連結:https://gitee.com/chenshuooooo/data-acquisition/tree/master/%E4%BD%9C%E4%B8%9A3/%E7%AC%AC%E4%B8%89%E9%A2%98
1.items類
2.settings
3.爬蟲db.py
# -*- coding:utf-8 -*-
from urllib.request import Request
import scrapy
import re
from douban.items import DoubanItem
class DbSpider(scrapy.Spider):
def start_requests(self):
##翻頁處理
for i in range(10):
url = 'https://movie.douban.com/top250?start=' + str(i * 25) + '&filter='
yield Request(url=url, callback=self.parse1)
##xpath選擇對應的專案內容傳入item
def parse1(self, response):
global count
data = response.body.decode()
selector = scrapy.Selector(text=data)
# 獲取每個電影專案
movies = selector.xpath(
"//ol[@class='grid_view']/li")
##選擇每個電影標籤下的對應標籤內容
for i in movies:
image = i.xpath("./div[@class='item']/div[@class='pic']/a/img/@src").extract_first()
name = i.xpath(
"./div[@class='item']/div[@class='info']/div[@class='hd']//span[@class='title']/text()").extract_first()
dir = i.xpath(
"./div[@class='item']/div[@class='info']/div[@class='bd']/p[@class='']/text()").extract_first()
desp = i.xpath(
"./div[@class='item']/div[@class='info']/div[@class='bd']/p[@class='quote']/span/text()").extract_first()
grade = i.xpath(
"./div[@class='item']/div[@class='info']/div[@class='bd']/div/span[@class='rating_num']/text()").extract_first()
print(image)
##正則轉換導演和主演,便於後續獲取相應內容
dir = dir.replace(' ', '')
dir = dir.replace('\n', '')
dir = dir + '\n'
director = re.findall(r'導演:(.*?)\s', dir)
actor = re.findall(r'主演:(.*?)\n', dir)
count += 1
item = DoubanItem()
# 儲存到對應item
item['num'] = str(count)
item['name'] = str(name)
item['dir'] = str(director[0])
if (len(actor) != 0): ##由於有動畫片沒有演員或者由於導演名過長導致演員無法顯示,actor可能為空
item['act'] = str(actor[0])
else:
item['actor'] = 'null'
item['introduce'] = str(desp)
item['score'] = str(grade)
item['img'] = str(image)
yield item
pass
4.pipeline類
心得體會
進一步加深了對scrapy框架的瞭解,不過對管道類的使用還是不太熟悉,還要加強。