您好,登錄后才能下訂單哦!
爬取貓眼電影TOP100(http://maoyan.com/board/4?offset=90)
1). 爬取內(nèi)容: 電影名稱,主演, 上映時(shí)間,圖片url地址保存到文件中;
2). 文件名為topMovie.csv;
3). 記錄方式: 電影名稱:主演:上映時(shí)間:圖片url地址:評(píng)分;
4). 并爬取的信息保存在數(shù)據(jù)庫(kù)中;
5). 使用多線程/線城池實(shí)現(xiàn);
1.利用多線程分配任務(wù)
2.編寫單線程的任務(wù)實(shí)現(xiàn)功能
(1)獲取指定url頁(yè)面信息。
(2)從指定信息中匹配所需的信息。
(3)將獲取到的信息分別保存至文件并寫入數(shù)據(jù)庫(kù)中。
from multiprocessing.pool import ThreadPool
def main():
# 需要訪問10個(gè)分頁(yè),生成對(duì)應(yīng)的urls列表
urls = [getPageInfo('https://maoyan.com/board/4?offset=%s' % i)for i in range(0,91,10)]
pool = ThreadPool(10) # 創(chuàng)建線程池對(duì)象,上限為10個(gè)
pool.map(getInfoInPage,urls) # 獲取信息并保存至文件
pool.close() # 關(guān)閉線程池
pool.join() # 等待子線程結(jié)束
# 獲取頁(yè)面信息
def getPageInfo(url):
pageObj = urlopen(url)
pageInfo = pageObj.read().decode('utf-8')
return pageInfo
page = 0 # 定義全局變量便于分頁(yè)存儲(chǔ)
def savePageInfo(pageInfo):
global page
page += 1
with open('doc/moviePage%s'%(page),'w',encoding='utf-8')as f:
f.write(pageInfo)
return pageInfo
def connetion():
return pymysql.connect(
host='localhost',
user='root',
password='mysql',
database='topMovie',
charset='utf8',
autocommit=True
)
def getInfoInPage(page1):
# 將獲取的html源碼加工為美味湯(便于獲取對(duì)應(yīng)的信息)
soup = BeautifulSoup(page1, 'html.parser')
# 遍歷單個(gè)頁(yè)面中 class 為 content 的div標(biāo)簽
for page in soup.find_all('div', {'class': "content"}):
# 遍歷content節(jié)點(diǎn)中的dd標(biāo)簽
for movie in page.find_all('dd'):
# 將soup節(jié)點(diǎn)轉(zhuǎn)化成字符串
movieInfo = str(movie)
# 篩選出需要的信息
name = movie.find('p', {'class': "name"}).text # 獲取電影名稱
star = re.findall(r'主演:(.*?)\s', movieInfo)[0] # 獲取主演
releaseTime = re.findall(r'上映時(shí)間:(.*?)<', movieInfo)[0] # 獲取上映時(shí)間
imgUrl = re.findall(r'"(http.*?)"', movieInfo)[0] # 獲取宣傳圖片地址
score = movie.find('p', {'class': "score"}).text # 獲取評(píng)分
# 電影名稱: 主演:上映時(shí)間: 圖片url地址:評(píng)分;
oneMovieInfo = '\n{0}:{1}:{2}:{3}:{4}'.format(name, star, releaseTime, imgUrl, score)
# 寫入文件
with open('doc/topMovie.csv', 'a+', encoding='utf-8')as f:
f.write(oneMovieInfo)
# 單個(gè)電影信息存入數(shù)據(jù)庫(kù)的sql語(yǔ)句
insertSql = 'insert into topmovie(電影名稱,主演,上映時(shí)間,圖片地址,評(píng)分) value("{0}","{1}","{2}","{3}","{4}")'.format(name, star, releaseTime, imgUrl, score)
lock.acquire() # 加上線程鎖,防止多線程公用連接出現(xiàn)問題
cur.execute(insertSql) # 執(zhí)行插入語(yǔ)句
lock.release() # 解鎖
多線程公用數(shù)據(jù)庫(kù)如果不進(jìn)行安全處理,有時(shí)會(huì)因?yàn)?
數(shù)據(jù)來不及回滾而其他線程進(jìn)行數(shù)據(jù)操作,從而導(dǎo)致存儲(chǔ)出現(xiàn)問題
可以通過一下幾種方式調(diào)整:
1.讓每個(gè)線程擁有自己的連接。
2.利用線程鎖來保證單次操作的完整性。
這里采用第二種方式在屬性插入語(yǔ)句前后進(jìn)行加鎖和解鎖操作
lock.acquire() # 加上線程鎖,防止多線程公用連接出現(xiàn)問題
cur.execute(insertSql) # 執(zhí)行插入語(yǔ)句
lock.release() # 解鎖
def main():
with open('doc/topMovie.csv','w',encoding='utf-8')as f:
f.write('電影名稱: 主演:上映時(shí)間: 圖片url地址:評(píng)分;')
# 創(chuàng)建連接和游標(biāo)
global cur
global lock
conn = connetion()
cur = conn.cursor()
lock = threading.Lock()
# 刪除并創(chuàng)建一個(gè)新表(刷新每次寫入的數(shù)據(jù))
dropSql = 'drop table topMovie;'
cur.execute(dropSql)
createSql = 'create table topMovie(電影名稱 varchar(100),主演 varchar(100),上映時(shí)間 varchar(100),圖片地址 varchar(100),評(píng)分 varchar(100))default charset=utf8'
cur.execute(createSql)
# 生成分頁(yè)的urls
urls = [getPageInfo('https://maoyan.com/board/4?offset=%s' % i)for i in range(0,91,10)]
# 實(shí)現(xiàn)多線程
pool = ThreadPool(10)
pool.map(getInfoInPage,urls) # 獲取信息并保存至文件
# 關(guān)閉線程池并等待子線程結(jié)束
pool.close()
pool.join()
# 關(guān)閉游標(biāo)和連接
cur.close()
conn.close()
import re
import threading
import time
from multiprocessing.pool import ThreadPool
import pymysql
from bs4 import BeautifulSoup
from urllib.request import urlopen
# 獲取頁(yè)面信息
def getPageInfo(url):
pageObj = urlopen(url)
pageInfo = pageObj.read().decode('utf-8')
return pageInfo
page = 0
# 保存頁(yè)面信息到文件moviePage
def savePageInfo(pageInfo):
global page
page += 1
with open('doc/moviePage%s'%(page),'w',encoding='utf-8')as f:
f.write(pageInfo)
return pageInfo
# 計(jì)時(shí)器
def timeCounter(fun):
def wrapper(*args,**kwargs):
startTime = time.time()
res = fun(*args,**kwargs)
endTime = time.time()
print(fun.__name__+'使用時(shí)間為%.2f'%(endTime-startTime))
return res
return wrapper
# 建立數(shù)據(jù)庫(kù)連接
def connetion():
return pymysql.connect(
host='localhost',
user='root',
password='mysql',
database='topMovie',
charset='utf8',
autocommit=True
)
# 從單頁(yè)源碼中獲取所需要的信息,并分別存至數(shù)據(jù)庫(kù)和文件參數(shù)為頁(yè)面源碼(str)
def getInfoInPage(page1):
soup = BeautifulSoup(page1, 'html.parser')
for page in soup.find_all('div', {'class': "content"}):
for movie in page.find_all('dd'):
# 將soup節(jié)點(diǎn)轉(zhuǎn)化成字符串
movieInfo = str(movie)
# 篩選出需要的信息
name = movie.find('p', {'class': "name"}).text
star = re.findall(r'主演:(.*?)\s', movieInfo)[0]
releaseTime = re.findall(r'上映時(shí)間:(.*?)<', movieInfo)[0]
imgUrl = re.findall(r'"(http.*?)"', movieInfo)[0]
score = movie.find('p', {'class': "score"}).text
# 電影名稱: 主演:上映時(shí)間: 圖片url地址:評(píng)分;
oneMovieInfo = '\n{0}:{1}:{2}:{3}:{4}'.format(name, star, releaseTime, imgUrl, score)
# 寫入文件
with open('doc/topMovie.csv', 'a+', encoding='utf-8')as f:
f.write(oneMovieInfo)
# 存入數(shù)據(jù)庫(kù)
insertSql = 'insert into topmovie(電影名稱,主演,上映時(shí)間,圖片地址,評(píng)分) value("{0}","{1}","{2}","{3}","{4}")'.format(name, star, releaseTime, imgUrl, score)
lock.acquire()
cur.execute(insertSql)
lock.release()
print(oneMovieInfo)
@timeCounter
def main():
with open('doc/topMovie.csv','w',encoding='utf-8')as f:
f.write('電影名稱: 主演:上映時(shí)間: 圖片url地址:評(píng)分;')
# 創(chuàng)建連接和游標(biāo)
conn = connetion()
global cur
cur = conn.cursor()
global lock
lock = threading.Lock()
# 創(chuàng)建一個(gè)新表
dropSql = 'drop table topMovie;'
cur.execute(dropSql)
createSql = 'create table topMovie(電影名稱 varchar(100),主演 varchar(100),上映時(shí)間 varchar(100),圖片地址 varchar(100),評(píng)分 varchar(100))default charset=utf8'
cur.execute(createSql)
urls = [getPageInfo('https://maoyan.com/board/4?offset=%s' % i)for i in range(0,91,10)]
pool = ThreadPool(10)
# pool.map(savePageInfo,urls)
pool.map(getInfoInPage,urls) # 獲取信息并保存至文件
pool.close()
pool.join()
cur.close()
conn.close()
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。