刚开始学习爬虫,按照网上的一个项目实战的视频学会了爬取一个网站的图片,然后就想着把自己之前看的《凡人修仙传》(以前手机的读书APP是可以免费看的,现在要收费,但是电脑上的网页是可以看的)爬取一下。
遇到的问题
看完视屏觉得可以直接套用代码来爬取,结果发现视频中的代码只能够爬取静态页面,对于动态加载的页面没有办法爬取。网上找了下方法,对于动态网页有两种方式,一种是逆向分析协议包找到脚本请求的网址,然后直接用代码来请求;另一种是使用selenium模块来模拟浏览器的行为,然后抓取数据。
两种方法分析:第一种是速度最快的,但是对于我这种小白来说有一定的难度,所以就放弃了;选择使用第二种方法。
代码完成的整个步骤
1、安装ChromeDriver和selenium模块
百度了一些方法,最后选择了一个博客的方法,链接找不到了,那就简单描述一下:
- 查看自己chrome的版本,到chromedriver下载地址上面找到对应的版本下载就可以。这里以我自己的浏览器为例,我的chrome是80.0.3987.122版本,但是网站上就只有如下的版本,当时比较困惑不知道要选择哪一个下载,后面再google的官方网站了解到只要是大版本号对应就可以。
我选择了上面的一个下载(因为点进去查看notes的时候发现上面的一个的更新日期比较新)。 - 将chromedriver.exe放到chrome.exe的目录下,然后环境变量中的系统路径添加这个路径;
- 使用pycharm安装selenium模块,from selenium import webdriver driver = webdriver.Chrome()这两句来进行测试,我的报错,然后就重启了一下电脑就OK了;
2、代码讲解
代码我直接全部写在了main里面了,
1、获得所有章节的网页地址
def getHtml(http_url):
header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36"}
response = requests.get(http_url,headers = header)
return response.text
def main():
#获取所有章节的地址
novel_url = "https://www.booktxt.net/1_1562"#
content = getHtml(novel_url)
pattern = re.compile(r'"5(.*?).html"')#正则匹配
novel_num = pattern.findall(content)
novel_url_list = [novel_url+"/5"+element for element in novel_num]
2、设置chrome为headless模式(不显示界面)
#设置无头浏览
chrome_options = Options()
chrome_options.add_argument('--headless')
#只打开一个浏览器(不需要放到循环里面)
driver = webdriver.Chrome(chrome_options = chrome_options)
3、遍历每一章的网址,抓取内容并保存
count = 1 #计数,放到保存的每一章的文件前面,方便排序
for url in novel_url_list:
driver.get(url)#打开网页
content_text = driver.find_element_by_id("content").text #使用id属性抓取本章的内容
head = driver.find_element_by_xpath("//div[@class = 'bookname']/h1").text #使用xpath格式抓取章节名称
#保存内容到文件
dir_path = "./凡人修仙"
if not os.path.exists(dir_path):
os.makedirs(dir_path)
head = re.sub('[\/:*?"<>|]', '', head)# 去掉章节名中的非法字符,因为要以这个名字作为txt文件的名称
fileName = dir_path+"/"+str(count)+head+".txt"
file = open(fileName,"w",encoding="utf-8")
file.write(content_text)
file.close()
print("当前下载章章数为:%d"%count) #输出信息,方便查看
# print("网址为%s"%url)
count +=1
4、最后的效果图
3、完整代码
import os
import re
import requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def getHtml(http_url):
header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36"}
response = requests.get(http_url,headers = header)
return response.text
def main():
#获取一章的页面地址数据
novel_url = "https://www.booktxt.net/1_1562"
content = getHtml(novel_url)
pattern = re.compile(r'"5(.*?).html"')#正则匹配
novel_num = pattern.findall(content)
novel_url_list = [novel_url+"/5"+element for element in novel_num]
# print(novel_url_list)
#设置无头浏览
chrome_options = Options()
chrome_options.add_argument('--headless')
#打开一个浏览器
driver = webdriver.Chrome(chrome_options = chrome_options)
count = 1
for url in novel_url_list:
#获取一页的内容
driver.get(url)
try:
content_text = driver.find_element_by_id("content").text
head = driver.find_element_by_xpath("//div[@class = 'bookname']/h1").text
#print(head)
except Exception:
head = "第"+str(count)+"无此章节"
content_text = ""
pass
#保存内容到文件
dir_path = "./凡人修仙"
if not os.path.exists(dir_path):
os.makedirs(dir_path)
head = re.sub('[\/:*?"<>|]', '', head)# 去掉非法字符
fileName = dir_path+"/"+str(count)+head+".txt"
file = open(fileName,"w",encoding="utf-8")
file.write(content_text)
file.close()
print("当前下载章章数为:%d"%count)
print("网址为%s"%url)
count +=1
return
if __name__ == '__main__':
main()