寫了一個之前沒完成的項目,代碼優化不夠,速度有點慢,應該也有錯誤的地方,望大佬看了之后能給點建議。。。。。。。。。
這是開始的url,先看一下它的網頁結構:http://www.cymodel.net/deaafc/13143.html,可以觀察到,整個網頁大致分為六部分內容,中間的正文部分,右邊的四部分新聞板塊,還有最下面的一部分社會新聞。而每一個新聞鏈接點進去后又是一個相同模樣的頁面,爬取的目標是獲取到所有的新聞title和對應的url。下面是代碼,每部分鏈接的提取都差不多,利用find_all返回結果列表,然后再對列表進行遍歷。
1 import requests 2 from bs4 import BeautifulSoup 3 4 # response請求頁面的響應,all_url_lis用於存放所有頁面的utl,all_title_list用於存放所有頁面的title, 5 # i用來顯示當前爬取到第幾個頁面 6 7 8 def parse(response, all_url_list, all_title_list, i): 9 html = response.content # 先獲取二進制形式的內容,下面再進行轉換,否則會出現中文亂碼 10 html = str(html, encoding='utf-8') 11 soup = BeautifulSoup(html, 'lxml') # 利用Beautifulsoup解析庫 12 f = open('title_and_url.txt', 'a', encoding='utf-8') # 打開文件,存儲所有頁面的title和url 13 14 # 獲取正文 15 # content = soup.find(name='div', attrs={'class': 'main_article'}) 16 # p_list = content.find_all(name='p') 17 # for p in p_list: 18 # print(p.string) 19 20 flag = 0 # 用來標志當前頁面的url有多少已經存儲過了,后面可以作為結束循環的條件 21 22 # 獲取下方社會新聞 23 Sociology_list = soup.find_all(name='div', attrs={'class': 'r'}) 24 sociology_a_list = Sociology_list[0].find_all(name='a') 25 for a in sociology_a_list: 26 sociology_title = a.string 27 sociology_url = a.attrs.get('href') 28 # print(sociology_title, sociology_url) 29 # 判斷列表中是否已經存在這個頁面的url或title,實現去重 30 if sociology_url not in all_url_list and sociology_title not in all_title_list: 31 all_url_list.append(sociology_url) 32 all_title_list.append(sociology_title) 33 f.write(sociology_title + ' ' + sociology_url + '\n') 34 else: 35 flag += 1 36 37 # 獲取排行榜 38 Ranking_list = soup.find_all(name='ul', attrs={'class': 'tt', 'id': 'tt'}) 39 rank_a_list = Ranking_list[0].find_all(name='a') 40 for a in rank_a_list: 41 rank_title = a.string 42 rank_url = a.attrs.get('href') 43 # print(rank_title, rank_url) 44 if rank_url not in all_url_list and rank_title not in all_title_list: 45 all_url_list.append(rank_url) 46 all_title_list.append(rank_title) 47 f.write(rank_title + ' ' + rank_url + '\n') 48 else: 49 flag += 1 50 51 # 熱點推薦 52 hot_list = soup.find_all(name='ul', attrs={'class': 'ducheng_list'}) 53 hot_a_list = hot_list[0].find_all(name='a') 54 for a in hot_a_list: 55 hot_title = a.string 56 hot_url = a.attrs.get('href') 57 # print(hot_title, hot_url) 58 if hot_url not in all_url_list and hot_title not in all_title_list: 59 all_url_list.append(hot_url) 60 all_title_list.append(hot_title) 61 f.write(hot_title + ' ' + hot_url + '\n') 62 else: 63 flag += 1 64 65 # 熱點視頻 66 video_list = soup.find_all(name='ul', attrs={'class': 'tuku_list'}) 67 video_a_list = video_list[0].find_all(name='a') 68 for a in video_a_list: 69 video_title = a.string 70 video_url = a.attrs.get('href') 71 # print(video_title, video_url) 72 if video_url not in all_url_list and video_title not in all_title_list: 73 all_url_list.append(video_url) 74 all_title_list.append(video_title) 75 f.write(video_title + ' ' + video_url + '\n') 76 else: 77 flag += 1 78 79 # 要聞 80 yaowen_list = soup.find_all(name='ul', attrs={'class': 'yaowen_list'}) 81 yaowen_a_list = yaowen_list[0].find_all(name='a') 82 for a in yaowen_a_list: 83 yaowen_title = a.string 84 yaowen_url = a.attrs.get('href') 85 # print(yaowen_title, yaowen_url) 86 if yaowen_url not in all_url_list and yaowen_title not in all_title_list: 87 all_url_list.append(yaowen_url) 88 all_title_list.append(yaowen_title) 89 f.write(yaowen_title + ' ' + yaowen_url + '\n') 90 else: 91 flag += 1 92 93 f.close() 94 print('第{0}個頁面存儲完成'.format(i), flag) 95 # 一個頁面中有44條新聞。如果改頁面中的所有url都已經被存儲過了,則可以大致認為已經獲取到了所有的url 96 # 實際少了十三條 97 if flag == 44: 98 return flag 99 else: 100 return 101 102 103 if __name__ == '__main__': 104 all_url_list = [] 105 all_title_list = [] 106 url = 'http://www.cymodel.net/deaafc/13143.html' 107 all_url_list.append(url) 108 i = 0 109 while (True): 110 # 如果想要把all_url_list里面的每個頁面的url全部爬取一遍,則可以用這個條件作為循環結束 111 # 把下面的內嵌if和函數里面的if else注釋掉即可 112 if( i < len(all_url_list) ): 113 response = requests.get(url=all_url_list[i]) 114 flag = parse(response, all_url_list, all_title_list, i+1) 115 i += 1 116 if flag == 44: 117 print('已爬取大部分的url!!!!!') 118 break 119 else: 120 print('已爬取到所有的url!!!!!') 121 break
再寫的時候,主要遇到了兩個問題,一是如何實現去重,二是爬取到什么時候結束。
第一個問題的解決辦法是,先定義兩個列表,用於存放每個頁面的url和title,也就是all_url_liat和all_title_list,然后再每次存放url和title之前,先判斷列表里面有沒有這個url,如果沒有,則進行存儲,並添加到列表中。本來之定義了一個url的列表,但后來發現有的網頁之間url不同,title相同,里面的內容也相同,所以又加了一個all_title_list。用這種方法實現去重的好處是比較簡單,容易想到,但壞處是列表里面的元素過多,比較占內容,會有兩個具有四百多個元素的列表,而且每次添加數據前,都要過一遍列表,判斷要添加的url是否已經再列表中,這樣就會導致程序運行較慢。
第二個問題的解決辦法一是根據每個頁面未被存儲的url數量判斷,每個頁面中共有44個新聞的鏈接,如果改頁面中的44個鏈接都已經被存儲過了,那么就認為已經獲取到了大部分的url,第二種辦法是把all_url_list中的每個url都爬取一下,這樣能獲取到所有的新聞鏈接,但耗時有點長,代碼還需要優化。第一種辦法的獲取結果為416條,第二種辦法獲取到的是429條。
*****************************不積跬步,無以至千里。 *****************************
