python爬蟲之深度爬取實例


寫了一個之前沒完成的項目,代碼優化不夠,速度有點慢,應該也有錯誤的地方,望大佬看了之后能給點建議。。。。。。。。。

這是開始的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條。

*****************************不積跬步,無以至千里。 *****************************


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM