




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
題目概述實驗題目:實驗七網(wǎng)絡(luò)爬蟲。實驗要求與目的:熟悉爬蟲工作原理,用相關(guān)的python工具包實現(xiàn)網(wǎng)絡(luò)爬蟲。實驗內(nèi)容:爬取TOP250電影的所有短評以及電影的相關(guān)數(shù)據(jù)。爬取TOP250豆瓣電影所有短評,以及電影的相關(guān)信息,包括電影類型,上映時間,以及演員列表等信息。開發(fā)平臺及開源工具本次信息檢索實驗使用的是python語言,開發(fā)工具為PyCharm2021.3,操作系統(tǒng)為Windows10和Ubuntu18.04服務(wù)器,第三方庫均使用pip安裝。本次實驗使用的第三方庫主要有selenium(自動登錄與信息爬取)、matplotlib(詞頻統(tǒng)計可視化)、numpy(矩陣處理)、jieba(分詞)等。詳細設(shè)計文件說明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ā)出爬取每個movie的具體信息的request
(movie_link)
yieldRequest(movie_link,callback=self.parse_movie_item)pipeline.py#因為在process_item中會根據(jù)不同的Item進行不同的查詢防止爬取重復(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進行查詢是否重復(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,其中大部分代碼是破解模擬登錄時破解滑動驗證碼,由于代碼比較多,破解滑動驗證碼的具體代碼請自行查看。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():
('用戶名或密碼錯誤')
#如果不需要驗證碼直接登錄成功
ifself.login_successfully():
('不需要驗證碼直接登錄成功')
#登陸成功以后跳回原來的頁面
self.browser.get(current_url)
else:
#需要驗證碼的情況下登錄
self.login_with_auth()
ifself.login_successfully():
('需要驗證碼的情況下登錄成功')
#登陸成功以后跳回原來的頁面
self.browser.get(current_url)
elifself.password_error():
('需要驗證碼的情況下登錄,用戶名或密碼錯誤')
else:
('需要驗證碼的情況下登錄,登錄失敗')
exceptNoSuchElementException:
('現(xiàn)在不需要登錄,所以找不到登錄元素')
#需要讓瀏覽器模擬隨機滑動頁面,模擬人的行為
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短評的爬取過程和電影信息爬取略有不同,因為在爬取短評大約40分鐘之后就會無法爬取,查看日志文件發(fā)現(xiàn)報錯全是Retry,估計是被檢測到異常暫時不允許訪問,所以寫一個shell腳本,每隔40分鐘啟動一次爬蟲,因為每次爬蟲都是爬取幾部電影的短評,所以在一個txt文件中寫一個接下來要爬取的電影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))
#后面可以加一個從數(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一段時間
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:
#然后可以爬取每個movie的短評信息
(request_comments_link)
yieldRequest(url=request_comments_link,callback=self.parse_comments)
else:
(request_comments_link)
('該鏈接已經(jīng)爬取過')commenters.py現(xiàn)階段爬取評論者的問題主要是速度太慢,畢竟一個網(wǎng)頁最多只有一個用戶的信息,再就是爬取時間過長也容易遇到Retry的問題,打算后面考慮一下有沒有什么彌補措施。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)頁時一些異常情況的處理,比如賬號已注銷,賬號已被永久停用等...其他地方和前面的爬蟲大同小異。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)注銷賬號的用戶會出錯
('該用戶已經(jī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:
#因為有的賬號根據(jù)log查看后發(fā)現(xiàn)是被永久停用的,沒法獲取注冊時間
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ù)用戶管理細則,帳號已被永久停用。
('該依據(jù)用戶管理細則,帳號已被永久停用')
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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025至2030中國聯(lián)苯菊酯市場運行動態(tài)及發(fā)展趨勢研究報告
- 2025至2030中國綠化植物培育產(chǎn)業(yè)現(xiàn)狀動態(tài)及經(jīng)營效益研究報告
- 2025至2030中國納米離子蒸臉器行業(yè)應(yīng)用前景及發(fā)展契機可行性報告
- 2025至2030中國電子游戲機市場應(yīng)用前景與需求態(tài)勢預(yù)測研究報告
- 2025至2030中國污水源熱泵市場融資渠道及應(yīng)用領(lǐng)域拓展建議報告
- 2025至2030中國水工金屬結(jié)構(gòu)行業(yè)投資建議及重點企業(yè)競爭力研究報告
- 2025至2030中國橡膠金屬減震器市場供需監(jiān)測及多元化發(fā)展方向報告
- 2025年量化投資策略在區(qū)塊鏈行業(yè)市場風險收益評估報告
- 2025至2030中國建筑器材租賃行業(yè)現(xiàn)狀調(diào)查與前景策略研究報告
- 2025年湖北省各市(州、區(qū))供電服務(wù)有限公司招聘筆試參考題庫含答案解析
- 私人合同協(xié)議書模板
- 神經(jīng)鞘瘤MRI診斷要點及鑒別診斷課件
- 120個常見文言實詞例釋-高考語文考前復(fù)習速記清單
- T-CEPPEA 5002-2019 電力建設(shè)項目工程總承包管理規(guī)范
- GA 1812.2-2024銀行系統(tǒng)反恐怖防范要求第2部分:數(shù)據(jù)中心
- 2025年端午節(jié)撞上兒童節(jié)活動方案
- 法治護航成長路-四年級法制教育專題
- 電工技能培訓課件下載
- 衛(wèi)生管理醫(yī)療戰(zhàn)略考題及答案
- 有色金屬礦山井巷工程質(zhì)量驗收規(guī)范
評論
0/150
提交評論