網絡空間安全概論 實驗7網絡爬蟲 爬取TOP250電影_第1頁
網絡空間安全概論 實驗7網絡爬蟲 爬取TOP250電影_第2頁
網絡空間安全概論 實驗7網絡爬蟲 爬取TOP250電影_第3頁
網絡空間安全概論 實驗7網絡爬蟲 爬取TOP250電影_第4頁
網絡空間安全概論 實驗7網絡爬蟲 爬取TOP250電影_第5頁
已閱讀5頁,還剩3頁未讀, 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

題目概述實驗題目:實驗七網絡爬蟲。實驗要求與目的:熟悉爬蟲工作原理,用相關的python工具包實現網絡爬蟲。實驗內容:爬取TOP250電影的所有短評以及電影的相關數據。爬取TOP250豆瓣電影所有短評,以及電影的相關信息,包括電影類型,上映時間,以及演員列表等信息。開發平臺及開源工具本次信息檢索實驗使用的是python語言,開發工具為PyCharm2021.3,操作系統為Windows10和Ubuntu18.04服務器,第三方庫均使用pip安裝。本次實驗使用的第三方庫主要有selenium(自動登錄與信息爬取)、matplotlib(詞頻統計可視化)、numpy(矩陣處理)、jieba(分詞)等。詳細設計文件說明douban_movies.py主要就是構造TOP250排行榜每一頁的鏈接,然后解析每一頁的電影名和電影頁鏈接,然后發出爬取電影頁信息的Request,之后利用xpath或者pyquery正常解析網頁信息即可。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

#然后發出爬取每個movie的具體信息的request

(movie_link)

yieldRequest(movie_link,callback=self.parse_movie_item)pipeline.py#因為在process_item中會根據不同的Item進行不同的查詢防止爬取重復的信息,所以對不同的collection設置了不同的索引,畢竟最后爬取到的短評有33萬多條,設置一下索引對速度還是有提升的

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主要是根據不同的Item進行查詢是否重復和插入

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:

('現在不需要登錄,所以找不到登錄元素')

#需要讓瀏覽器模擬隨機滑動頁面,模擬人的行為

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分鐘之后就會無法爬取,查看日志文件發現報錯全是Retry,估計是被檢測到異常暫時不允許訪問,所以寫一個shell腳本,每隔40分鐘啟動一次爬蟲,因為每次爬蟲都是爬取幾部電影的短評,所以在一個txt文件中寫一個接下來要爬取的電影index,一開始是0,每次爬蟲都會+10,所以經過25次就能結束爬蟲,具體爬取的思路和電影信息的爬蟲差不多。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))

#后面可以加一個從數據庫中讀取已爬取的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)

('該鏈接已經爬取過')commenters.py現階段爬取評論者的問題主要是速度太慢,畢竟一個網頁最多只有一個用戶的信息,再就是爬取時間過長也容易遇到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)評論者信息爬取過程和前面其他爬蟲最大的不同就是解析網頁時一些異常情況的處理,比如賬號已注銷,賬號已被永久停用等...其他地方和前面的爬蟲大同小異。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:

#已經注銷賬號的用戶會出錯

('該用戶已經主動注銷帳號')

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:

#因為有的賬號根據log查看后發現是被永久停用的,沒法獲取注冊時間

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:

#這種情況是依據用戶管理細則,帳號已被永久停用。

('該依據用戶管理細則,帳號已被永久停用')

return

following_num=response.xpath('//*[@id="friend"]/h2/span/a/text()').extract()

try:

following_num=following_num[0]

#截取成員xxx中的數字

commenter_info_item['following_num']=following_num[2:]

exceptIndexError:

#如果沒有關注的人的話沒有用戶關注多少人,但會有被0人關注

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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論