python爬蟲7:實戰1
前言
? python實現網絡爬蟲非常簡單,只需要掌握一定的基礎知識和一定的庫使用技巧即可。本系列目標旨在梳理相關知識點,方便以后復習。
申明
? 本系列所涉及的代碼僅用于個人研究與討論,并不會對網站產生不好影響。
目錄結構
文章目錄
- python爬蟲7:實戰1
- 1. 目標
- 2. 詳細流程
- 2.1 找到目標小說
- 2.2 獲取小說章節目錄
- 2.3 獲取小說內容
- 2.4 完整代碼
- 3. 總結
1. 目標
? 這次爬蟲實戰,采用的庫為:requests + lxml
,這次以爬取一部小說為目標,具體的網站老規矩就不給了,大家學習思路最重要。
? 再次說明,案例本身并不重要,重要的是如何去使用和分析,另外為了避免侵權之類的問題,我不會放涉及到網站的圖片,希望能理解。
2. 詳細流程
2.1 找到目標小說
第一步,確定get請求的url
? 假設我們的網站為:https://xxxxxxx.com
,那么,我們首先需要找到搜索框,然后隨意搜索幾本小說,比如這里我搜索的是圣墟
、萬族之劫
,那么觀察網頁上的url變化,如下:
https://xxxxx?q=圣墟
https://xxxxx?q=萬族之劫
? 可以看出,這里是get
請求,并且參數名為q
。
第二步,正確請求網頁
? 我們可以寫下第一個代碼了,目標是獲取想要的小說,代碼如下:
# 都要用到的參數
HEADERS = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
}# 獲取搜索某小說后的頁面
def get_search_result():# 網址url = 'xxxxx'# 請求參數search = input('請輸入想要搜索的小說:')params = {'q' : search}# 請求response = requests.get(url,headers=HEADERS,params=params)# 把獲取到的網頁保存到本地with open('search.html','w',encoding='utf-8') as f:f.write(response.content.decode('utf-8'))
? 結果如下:
? 可以看出,獲取到正確的網頁,說明這一步我們完成了。
正確解析網頁,以獲取小說鏈接
? 上面,我們已經把網頁源碼存放到了本地一個名為search.html
的文件,下面我們來解析它。
? 解析它,首先需要明確我們要獲取什么節點、什么值。看下面:
? 可以看出,我們的目標標簽位于div[class="mshow"]下的table[class="grid"]下的td下的a標簽
,并且我們需要獲取這個a標簽的href屬性和文本值。除此之外,href屬性值只是部分地址,需要跟網站根地址xxxx.com
拼湊再一起。
? 基于此,可以完成代碼:
# 解析網頁
def parse_search_result():# 打開文件,讀取文件with open('search.html','r',encoding='utf-8') as f:content = f.read()# 基礎urlbase_url = 'xxxxxx.com/'# 初始化lxmlhtml = etree.HTML(content)# 獲取目標節點href_list = html.xpath('//div[@class="show"]//table[@class="grid"]//td//a/@href')text_list = html.xpath('//div[@class="show"]//table[@class="grid"]//td//a/text()')# 處理內容值url_list = [base_url+href for href in href_list]# 選擇要爬取的小說for i,text in enumerate(text_list):print('當前小說名為:',text)decision = input('是否爬取它(只能選擇一本),Y/N:')if decision == 'Y':return url_list[i],text
? 運行結果如下:
2.2 獲取小說章節目錄
第一步,請求頁面
? 首先,我們去請求上面獲取的網頁,這里就比較簡單了,基本上把上面的請求代碼拷貝過來修改修改即可:
# 請求目標小說網站
def get_target_book(url):# 請求response = requests.get(url,headers=HEADERS)# 保存源碼with open('book.html','w',encoding='utf-8') as f:f.write(response.content.decode('utf-8'))
? 可以看到保存到本地的結果如下:
? 可以看出,這一步成功了。
第二步,解析上面的網頁,獲取不同章節的鏈接
? 這一步,主要的難點在于解析網頁,首先,看下面:
? 由于該網頁小說章節都分為兩個部位,第一個為最新章節
,第二個為全部章節
,而第二個才是我們需要獲取的,因此xpath語法應該為:
//div[@class="show"]//div[contains(@class,'showBox') and position()=3]//ul//a
? 那么,可以完成代碼如下:
# 解析章節網頁
def parse_chapter(base_url):# 打開文件,讀取內容with open('book.html','r',encoding='utf-8') as f:content = f.read()# 初始化html = etree.HTML(content)# 解析href_list = html.xpath('//div[@class="show"]//div[contains(@class,"showBox") and position()=3]//ul//a/@href')text_list = html.xpath('//div[@class="show"]//div[contains(@class,"showBox") and position()=3]//ul//a/text()')# 處理:拼湊出完整網頁url_list = [base_url+url for url in href_list]# 返回結果return url_list,text_list
? 運行結果如下:
2.3 獲取小說內容
? 這里我們就不分開了,直接獲取源碼后直接解析。那么這里說明一下解析原理,看下面:
? 可以輕松知道xpath語法:
//div[contains(@class,'book')]//div[@id='content']//text()
? 那么,代碼如下:
# 請求小說頁面
def get_content(url,title):# 請求response = requests.get(url,headers=HEADERS)# 獲取源碼content = response.content.decode('utf-8')# 初始化html = etree.HTML(content)# 解析text_list = html.xpath('//div[contains(@class,"book")]//div[@id="content"]//text()')# 后處理# 首先,把第一個和最后一個的廣告信息去掉text_list = text_list[1:-1]# 其次,把里面的空白字符和\xa0去掉text_list = [text.strip().replace('\xa0','') for text in text_list]# 最后,寫入文件即可with open(title+'.txt','w',encoding='utf-8') as g:for text in text_list:g.write(text+'\n')
? 運行結果如下:
? 可以看出,成功實現。
2.4 完整代碼
? 完整代碼如下:
# author : 自學小白菜
# -*- coding:utf-8 -*-'''
# File Name : 7 lxml_novel.py
# Create Time : 2023/8/5 22:04
# Version : python3.7
# Description : 實戰1:爬取小說
'''# 導包
import requests
from lxml import etree# 都要用到的參數
HEADERS = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
}# 獲取搜索某小說后的頁面
def get_search_result():# 網址url = 'https://www.iwurexs.net/so.html'# 請求參數search = input('請輸入想要搜索的小說:')params = {'q' : search}# 請求response = requests.get(url,headers=HEADERS,params=params)# 把獲取到的網頁保存到本地with open('search.html','w',encoding='utf-8') as f:f.write(response.content.decode('utf-8'))# 解析網頁
def parse_search_result():# 打開文件,讀取文件with open('search.html','r',encoding='utf-8') as f:content = f.read()# 基礎urlbase_url = 'https://www.iwurexs.net/'# 初始化lxmlhtml = etree.HTML(content)# 獲取目標節點href_list = html.xpath('//div[@class="show"]//table[@class="grid"]//td//a/@href')text_list = html.xpath('//div[@class="show"]//table[@class="grid"]//td//a/text()')# 處理內容值url_list = [base_url+href for href in href_list]# 選擇要爬取的小說for i,text in enumerate(text_list):print('當前小說名為:',text)decision = input('是否爬取它(只能選擇一本),Y/N:')if decision == 'Y':return url_list[i],text# 請求目標小說網站
def get_target_book(url):# 請求response = requests.get(url,headers=HEADERS)# 保存源碼with open('book.html','w',encoding='utf-8') as f:f.write(response.content.decode('utf-8'))# 解析章節網頁
def parse_chapter(base_url):# 打開文件,讀取內容with open('book.html','r',encoding='utf-8') as f:content = f.read()# 初始化html = etree.HTML(content)# 解析href_list = html.xpath('//div[@class="show"]//div[contains(@class,"showBox") and position()=3]//ul//a/@href')text_list = html.xpath('//div[@class="show"]//div[contains(@class,"showBox") and position()=3]//ul//a/text()')# 處理:拼湊出完整網頁url_list = [base_url+url for url in href_list]# 返回結果return url_list,text_list# 請求小說頁面
def get_content(url,title):# 請求response = requests.get(url,headers=HEADERS)# 獲取源碼content = response.content.decode('utf-8')# 初始化html = etree.HTML(content)# 解析text_list = html.xpath('//div[contains(@class,"book")]//div[@id="content"]//text()')# 后處理# 首先,把第一個和最后一個的廣告信息去掉text_list = text_list[1:-1]# 其次,把里面的空白字符和\xa0去掉text_list = [text.strip().replace('\xa0','') for text in text_list]# 最后,寫入文件即可with open(title+'.txt','w',encoding='utf-8') as g:for text in text_list:g.write(text+'\n')if __name__ == '__main__':# 第一步,獲取到搜索頁面的源碼# get_search_result()# 第二步,進行解析target_url,name = parse_search_result()# 第三步,請求目標小說頁面get_target_book(target_url)# 第四步,解析章節網頁url_list,text_list = parse_chapter(target_url)for url,title in zip(url_list,text_list):# 第五步,請求小說具體的某個章節并直接解析get_content(url,title)break
3. 總結
? 上面代碼還不完善,存在一定優化的地方,比如代碼有些地方可以解耦,另外,必須限制訪問速度,不然后期容易被封掉IP,除此之外,可以考慮代理池構建等操作。