




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
題目概述實(shí)驗(yàn)題目:實(shí)驗(yàn)七網(wǎng)絡(luò)爬蟲。實(shí)驗(yàn)要求與目的:熟悉爬蟲工作原理,用相關(guān)的python工具包實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲。實(shí)驗(yàn)內(nèi)容:爬取TOP250電影的所有短評以及電影的相關(guān)數(shù)據(jù)。爬取TOP250豆瓣電影所有短評,以及電影的相關(guān)信息,包括電影類型,上映時(shí)間,以及演員列表等信息。開發(fā)平臺及開源工具本次信息檢索實(shí)驗(yàn)使用的是python語言,開發(fā)工具為PyCharm2021.3,操作系統(tǒng)為Windows10和Ubuntu18.04服務(wù)器,第三方庫均使用pip安裝。本次實(shí)驗(yàn)使用的第三方庫主要有selenium(自動(dòng)登錄與信息爬取)、matplotlib(詞頻統(tǒng)計(jì)可視化)、numpy(矩陣處理)、jieba(分詞)等。詳細(xì)設(shè)計(jì)文件說明douban_movies.py主要就是構(gòu)造TOP250排行榜每一頁的鏈接,然后解析每一頁的電影名和電影頁鏈接,然后發(fā)出爬取電影頁信息的Request,之后利用xpath或者pyquery正常解析網(wǎng)頁信息即可。defstart_requests(self):
base_url='/top250?start=$&filter='
forstartinrange(10):
url=str.replace(base_url,'$',str(start*25))
(url)
yieldRequest(url,callback=self.parse_top250)
defparse_top250(self,response):
top250_movie_info_item=TOP250MovieInfoItem()
html=response.text
doc=pq(html)
all_movies=doc('#content>div>div.article>ol>li>div>')
formovieinall_movies.items():
sleep_time=random.uniform(0.5,1)
time.sleep(sleep_time)
movie_link=movie('div.hd>a').attr('href')
title=movie('div.hd>a>span.title').text()
top250_movie_info_item['title']=title
top250_movie_info_item['movie_link']=movie_link
(top250_movie_info_item)
yieldtop250_movie_info_item
#然后發(fā)出爬取每個(gè)movie的具體信息的request
(movie_link)
yieldRequest(movie_link,callback=self.parse_movie_item)pipeline.py#因?yàn)樵趐rocess_item中會根據(jù)不同的Item進(jìn)行不同的查詢防止爬取重復(fù)的信息,所以對不同的collection設(shè)置了不同的索引,畢竟最后爬取到的短評有33萬多條,設(shè)置一下索引對速度還是有提升的
defopen_spider(self,spider):
self.client=pymongo.MongoClient(self.mongo_uri)
self.db=self.client[self.mongo_db]
self.db[TOP250MovieInfoItem.collection].create_index([('movie_link',pymongo.ASCENDING)])
self.db[MovieInfoItem.collection].create_index([('movie_link',pymongo.ASCENDING)])
self.db[CommentInfoItem.collection].create_index([('commenter_link',pymongo.ASCENDING),('comment_page_link',pymongo.ASCENDING)])
self.db[CommenterInfoItem.collection].create_index([('commenter_link',pymongo.ASCENDING)])
#process_item主要是根據(jù)不同的Item進(jìn)行查詢是否重復(fù)和插入
defprocess_item(self,item,spider):
ifisinstance(item,TOP250MovieInfoItem):
condition={'movie_link':item.get('movie_link')}
elifisinstance(item,MovieInfoItem):
condition={'comments_link':item.get('comments_link')}
elifisinstance(item,CommentInfoItem):
condition={'commenter_link':item.get('commenter_link'),
'comment_page_link':item.get('comment_page_link')}
elifisinstance(item,CommenterInfoItem):
condition={'commenter_link':item.get('commenter_link')}
result=self.db[item.collection].find_one(condition)
ifresultisNone:
self.db[item.collection].insert(dict(item))
returnitemmiddleware.pymiddleware中只使用了SeleniumMiddleware,其中大部分代碼是破解模擬登錄時(shí)破解滑動(dòng)驗(yàn)證碼,由于代碼比較多,破解滑動(dòng)驗(yàn)證碼的具體代碼請自行查看。defprocess_request(self,request,spider):
('PhantomJSisStarting')
try:
self.browser.get(request.url)
time.sleep(1)
html=self.browser.page_source
current_url=request.url
try:
need_login=self.browser.find_element_by_xpath('//*[@id="db-global-nav"]/div/div[1]/a')
('需要登錄')
login_link=need_login.get_attribute('href')
self.open(login_link)
ifself.password_error():
('用戶名或密碼錯(cuò)誤')
#如果不需要驗(yàn)證碼直接登錄成功
ifself.login_successfully():
('不需要驗(yàn)證碼直接登錄成功')
#登陸成功以后跳回原來的頁面
self.browser.get(current_url)
else:
#需要驗(yàn)證碼的情況下登錄
self.login_with_auth()
ifself.login_successfully():
('需要驗(yàn)證碼的情況下登錄成功')
#登陸成功以后跳回原來的頁面
self.browser.get(current_url)
elifself.password_error():
('需要驗(yàn)證碼的情況下登錄,用戶名或密碼錯(cuò)誤')
else:
('需要驗(yàn)證碼的情況下登錄,登錄失敗')
exceptNoSuchElementException:
('現(xiàn)在不需要登錄,所以找不到登錄元素')
#需要讓瀏覽器模擬隨機(jī)滑動(dòng)頁面,模擬人的行為
random_scroll_nums=random.randint(0,1)
foriinrange(random_scroll_nums):
random_scroll_distance1=random.randint(200,5000)
js='varq=document.documentElement.scrollTop='+str(random_scroll_distance1)
self.browser.execute_script(js)
time.sleep(0.3)
random_scroll_distance2=random.randint(200,5000)
js='varq=document.documentElement.scrollTop='+str(random_scroll_distance2)
self.browser.execute_script(js)
time.sleep(0.3)
random_sleep=random.uniform(0.2,0.8)
time.sleep(random_sleep)
returnHtmlResponse(url=request.url,body=html,request=request,encoding='utf-8',
status=200)
exceptTimeoutException:
self.logger.error('self.browser.get(request.url)happenedTimeoutException')
returnHtmlResponse(url=request.url,status=500,request=request)
exceptException:
self.logger.error('self.browser.get(request.url)happenederror')
returnHtmlResponse(url=request.url,status=500,request=request)comments.py短評的爬取過程和電影信息爬取略有不同,因?yàn)樵谂廊《淘u大約40分鐘之后就會無法爬取,查看日志文件發(fā)現(xiàn)報(bào)錯(cuò)全是Retry,估計(jì)是被檢測到異常暫時(shí)不允許訪問,所以寫一個(gè)shell腳本,每隔40分鐘啟動(dòng)一次爬蟲,因?yàn)槊看闻老x都是爬取幾部電影的短評,所以在一個(gè)txt文件中寫一個(gè)接下來要爬取的電影index,一開始是0,每次爬蟲都會+10,所以經(jīng)過25次就能結(jié)束爬蟲,具體爬取的思路和電影信息的爬蟲差不多。defstart_requests(self):
#每次都要讀取這次要開始爬的電影的鏈接index
withopen('/home/zhiyong/data/next_link_num.txt','rt')asf:
#withopen('E:\PycharmProjects\some_data/next_link_num.txt','rt')asf:
next_link_index=f.read()
next_link_index=int(next_link_index)
#將后面開始讀的電影索引+10寫入文件
withopen('/home/zhiyong/data/next_link_num.txt','wt')asf:
#withopen('E:\PycharmProjects\some_data/next_link_num.txt','wt')asf:
new_next_link_index=next_link_index+10
f.write(str(new_next_link_index))
#后面可以加一個(gè)從數(shù)據(jù)庫中讀取已爬取的comment鏈接去重
movie_link_list=self.get_movie_link_list()
comment_page_link_list=self.get_comment_page_link_list()
forindexinrange(next_link_index,new_next_link_index):
ifindex>=250:
break
movie_link=movie_link_list[index]
time.sleep(3)
#分別爬取好評,中評,差評
choices=['h','m','l']
forchoiceinchoices:
#爬取每種評論之前先sleep一段時(shí)間
every_type_comments_sleep=random.randint(2,5)
time.sleep(every_type_comments_sleep)
comment_suffix='comments?start=$&limit=20&sort=new_score&status=P'
real_comments_link=movie_link+comment_suffix
ifchoice=='h':
real_comments_link=real_comments_link+'&percent_type=h'
elifchoice=='l':
real_comments_link=real_comments_link+'&percent_type=l'
else:
real_comments_link=real_comments_link+'&percent_type=m'
forstartinrange(25):
tmp_link=real_comments_link
request_comments_link=str.replace(tmp_link,'$',str(start*20))
ifrequest_comments_linknotincomment_page_link_list:
#然后可以爬取每個(gè)movie的短評信息
(request_comments_link)
yieldRequest(url=request_comments_link,callback=self.parse_comments)
else:
(request_comments_link)
('該鏈接已經(jīng)爬取過')commenters.py現(xiàn)階段爬取評論者的問題主要是速度太慢,畢竟一個(gè)網(wǎng)頁最多只有一個(gè)用戶的信息,再就是爬取時(shí)間過長也容易遇到Retry的問題,打算后面考慮一下有沒有什么彌補(bǔ)措施。defstart_requests(self):
commenter_link_list=self.get_commenter_link_list()
crawled_commenter_link_list=self.get_crawled_commenter_link_list()
forcommenter_linkincommenter_link_list:
ifcommenter_linknotincrawled_commenter_link_list:
crawled_commenter_link_list.append(commenter_link)
time.sleep(4)
(commenter_link)
yieldRequest(url=commenter_link,callback=self.parse_commenters)評論者信息爬取過程和前面其他爬蟲最大的不同就是解析網(wǎng)頁時(shí)一些異常情況的處理,比如賬號已注銷,賬號已被永久停用等...其他地方和前面的爬蟲大同小異。defparse_commenters(self,response):
commenter_info_item=CommenterInfoItem()
commenter_link=response.xpath('//*[@id="db-usr-profile"]/div[2]/ul/li[1]/a/@href').extract()
try:
commenter_link=commenter_link[0]
exceptIndexError:
#已經(jīng)注銷賬號的用戶會出錯(cuò)
('該用戶已經(jīng)主動(dòng)注銷帳號')
return
commenter_info_item['commenter_link']=commenter_link
location=response.xpath('//*[@id="profile"]/div/div[2]/div[1]/div/a/text()').extract()
iflocationisNone:
lcoation='未知'
else:
try:
location=location[0]
exceptIndexError:
lcoation='未知'
commenter_info_item['location']=location
register_timestamp=response.xpath('//*[@id="profile"]/div/div[2]/div[1]/div/div/text()[2]').extract()
try:
register_timestamp=register_timestamp[0]
#截取xxxx-xx-xx日期
result=re.findall('(.*)加入',register_timestamp)
register_timestamp=result[0]
register_timestamp=register_timestamp[0:10]
exceptIndexError:
#因?yàn)橛械馁~號根據(jù)log查看后發(fā)現(xiàn)是被永久停用的,沒法獲取注冊時(shí)間
register_timestamp=datetime.date.today()
commenter_info_item['register_timestamp']=register_timestamp
account_name=response.xpath('//*[@id="profile"]/div/div[2]/div[1]/div/div/text()[1]').extract()
try:
account_name=account_name[0]
account_name=str.strip(account_name)
commenter_info_item['account_name']=account_name[0]
exceptIndexError:
#這種情況是依據(jù)用戶管理細(xì)則,帳號已被永久停用。
('該依據(jù)用戶管理細(xì)則,帳號已被永久停用')
return
following_num=response.xpath('//*[@id="friend"]/h2/span/a/text()').extract()
try:
following_num=following_num[0]
#截取成員xxx中的數(shù)字
commenter_info_item['following_num']=following_num[2:]
exceptIndexError:
#如果沒有關(guān)注的人的話沒有用戶關(guān)注多少人,但會有被0人關(guān)注
following_num=0
follower_num=response.xpath('//*[@id="content"]/div/div[2]/p[1]/a/text()').extract()
follower_num=follower_num
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 房地產(chǎn)ERP軟件使用許可合同4篇
- 公司注冊商標(biāo)出讓合同書5篇
- 抵押保證借款合同范本一2篇
- 道路關(guān)鍵工程綜合施工合同3篇
- 血管栓塞劑及栓塞材料項(xiàng)目績效評估報(bào)告
- 新生兒骨折查房要點(diǎn)解析
- 2025西藏藏醫(yī)藥大學(xué)輔導(dǎo)員考試試題及答案
- 2025遼源職業(yè)技術(shù)學(xué)院輔導(dǎo)員考試試題及答案
- 2025珠??萍紝W(xué)院輔導(dǎo)員考試試題及答案
- 2025綏化市教育學(xué)院輔導(dǎo)員考試試題及答案
- 《中國共產(chǎn)主義青年團(tuán)紀(jì)律處分條例(試行)》含答案
- 2025年部編版新教材語文一年級下冊期末復(fù)習(xí)計(jì)劃及全冊單元復(fù)習(xí)課教案
- 企業(yè)信用評級與征信服務(wù)后續(xù)預(yù)案
- 《企業(yè)績效評價(jià)標(biāo)準(zhǔn)值(2023年版)》
- 2025年互聯(lián)網(wǎng)營銷師(直播銷售員)考試題庫
- 辦公室內(nèi)部規(guī)章制度及執(zhí)行細(xì)則
- 中考語文試卷名著閱讀專題匯編《艾青詩選》詩歌賞析題(截至2024年)
- 2025公考培訓(xùn)行業(yè)年度趨勢分析
- 第12課《我是小小消防員》(說課稿)蘇少版六年級上冊綜合實(shí)踐活動(dòng)
- 蔬菜生產(chǎn)實(shí)習(xí)總結(jié)
- 消防工程包清工合同范本年
評論
0/150
提交評論