網(wǎng)絡(luò)空間安全概論 實(shí)驗(yàn)7網(wǎng)絡(luò)爬蟲 爬取TOP250電影_第1頁
網(wǎng)絡(luò)空間安全概論 實(shí)驗(yàn)7網(wǎng)絡(luò)爬蟲 爬取TOP250電影_第2頁
網(wǎng)絡(luò)空間安全概論 實(shí)驗(yàn)7網(wǎng)絡(luò)爬蟲 爬取TOP250電影_第3頁
網(wǎng)絡(luò)空間安全概論 實(shí)驗(yàn)7網(wǎng)絡(luò)爬蟲 爬取TOP250電影_第4頁
網(wǎng)絡(luò)空間安全概論 實(shí)驗(yàn)7網(wǎng)絡(luò)爬蟲 爬取TOP250電影_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

題目概述實(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電影的所有短評(píng)以及電影的相關(guān)數(shù)據(jù)。爬取TOP250豆瓣電影所有短評(píng),以及電影的相關(guān)信息,包括電影類型,上映時(shí)間,以及演員列表等信息。開發(fā)平臺(tái)及開源工具本次信息檢索實(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中會(huì)根據(jù)不同的Item進(jìn)行不同的查詢防止爬取重復(fù)的信息,所以對(duì)不同的collection設(shè)置了不同的索引,畢竟最后爬取到的短評(píng)有33萬多條,設(shè)置一下索引對(duì)速度還是有提升的

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)證碼的具體代碼請(qǐng)自行查看。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短評(píng)的爬取過程和電影信息爬取略有不同,因?yàn)樵谂廊《淘u(píng)大約40分鐘之后就會(huì)無法爬取,查看日志文件發(fā)現(xiàn)報(bào)錯(cuò)全是Retry,估計(jì)是被檢測(cè)到異常暫時(shí)不允許訪問,所以寫一個(gè)shell腳本,每隔40分鐘啟動(dòng)一次爬蟲,因?yàn)槊看闻老x都是爬取幾部電影的短評(píng),所以在一個(gè)txt文件中寫一個(gè)接下來要爬取的電影index,一開始是0,每次爬蟲都會(huì)+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)

#分別爬取好評(píng),中評(píng),差評(píng)

choices=['h','m','l']

forchoiceinchoices:

#爬取每種評(píng)論之前先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的短評(píng)信息

(request_comments_link)

yieldRequest(url=request_comments_link,callback=self.parse_comments)

else:

(request_comments_link)

('該鏈接已經(jīng)爬取過')commenters.py現(xiàn)階段爬取評(píng)論者的問題主要是速度太慢,畢竟一個(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)評(píng)論者信息爬取過程和前面其他爬蟲最大的不同就是解析網(wǎng)頁時(shí)一些異常情況的處理,比如賬號(hào)已注銷,賬號(hào)已被永久停用等...其他地方和前面的爬蟲大同小異。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)注銷賬號(hào)的用戶會(huì)出錯(cuò)

('該用戶已經(jīng)主動(dòng)注銷帳號(hào)')

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)橛械馁~號(hào)根據(jù)log查看后發(fā)現(xiàn)是被永久停用的,沒法獲取注冊(cè)時(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ì)則,帳號(hào)已被永久停用。

('該依據(jù)用戶管理細(xì)則,帳號(hào)已被永久停用')

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)注多少人,但會(huì)有被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等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論