--- 好的方法很多,我們先掌握一種 ---
【背景】
對於網頁資訊的採集,靜態頁面我們通常都可以透過python的request.get()庫就能獲取到整個頁面的資訊。
但是對於動態生成的網頁資訊來說,我們透過request.get()是獲取不到。
【方法】
可以透過python第三方庫selenium來配合實現資訊獲取,採取方案:python + request + selenium + BeautifulSoup
我們拿縱橫中文網的小說採集舉例(注意:請檢視網站的robots協議找到可以爬取的內容,所謂盜亦有道):
思路整理:
1.透過selenium 定位元素的方式找到小說章節資訊
2.透過BeautifulSoup加工後提取章節標題和對應的各章節的連結資訊
3.透過request +BeautifulSoup 按章節連結提取小說內容,並將內容儲存下來
【上程式碼】
1.先在開發者工具中,除錯定位所需元素對應的xpath命令編寫方式
2.透過selenium 中find_elements()定位元素的方式找到所有小說章節,我們這裡定義一個方法接受引數來使用
def Get_novel_chapters_info(url:str,xpath:str,skip_num=None,chapters_num=None): # skip_num 需要跳過的採集章節(預設不跳過),chapters_num需要採集的章節數(預設全部章節) # 建立Chrome選項(禁用圖形介面) chrome_options = Options() chrome_options.add_argument("--headless") driver = webdriver.Chrome(options=chrome_options) driver.get(url) driver.maximize_window() time.sleep(3) # 採集小說的章節元素 catalogues_list = [] try: catalogues = driver.find_elements(By.XPATH,xpath) if skip_num is None: for catalogue in catalogues: catalogues_list.append(catalogue.get_attribute('outerHTML')) driver.quit() if chapters_num is None: return catalogues_list else: return catalogues_list[:chapters_num] else: for catalogue in catalogues[skip_num:]: catalogues_list.append(catalogue.get_attribute('outerHTML')) driver.quit() if chapters_num is None: return catalogues_list else: return catalogues_list[:chapters_num] except Exception: driver.quit()
3.把採集到的資訊透過beautifulsoup加工後,提取章節標題和連結內容
# 獲取章節標題和對應的連結資訊 title_link = {} for each in catalogues_list: bs = BeautifulSoup(each,'html.parser') chapter = bs.find('a') title = chapter.text link = 'https:' + chapter.get('href') title_link[title] = link
4.透過request+BeautifulSoup 按章節連結提取小說內容,並儲存到一個檔案中
# 按章節儲存小說內容 novel_path = '小說存放的路徑/小說名稱.txt' with open(novel_path,'a') as f: for title,url in title_link.items(): response = requests.get(url,headers={'user-agent':'Mozilla/5.0'}) html = response.content.decode('utf-8') soup = BeautifulSoup(html,'html.parser') content = soup.find('div',class_='content').text # 先寫章節標題,再寫小說內容 f.write('---小西瓜免費小說---' + '\n'*2) f.write(title + '\n') f.write(content+'\n'*3)