python爬虫——从此不用再愁找不到小说txt文件
最近在学习python,学了个大概就开始写爬虫了,之前做了个糗百的简单爬虫,然后底下还做了一些学校教务系统的爬虫,爬取了自己的成绩,看着挂科的大英,心中一万头草泥马走过,说下今天的正题
昨天才感觉自己的爬虫基础还不是很好,就准备做几个小程序练手,就想到了从小就看的电子小说,当时可以是千辛万苦才从网站找到的TXT文件,传到我的MP5上半夜偷偷看,现在想起来还是美滋滋,又跑偏了
于是乎,我准备做一个可以自动爬取一部电子小说TXT文件的程序
接下来就是百度“免费小说网”,然后选取了笔趣阁,进行了爬取,在这里感谢笔趣阁
我们要做的步骤
1. 输入你要寻找的小说全名并将其数据化传入请求访问的全书网搜索界面 ->
2. 找到搜索界面第一个小说的名字与你寻找的小说名字匹配,如果匹配失败则提示并退出,成功则提取第一个小说的网址进行访问 ->
3. 访问小说文章页面,并且提取所有章节的链接进行后续访问 ->
4. 最后进每一章内容的抓取,保存到本地txt文件中 ->Over
One
首先要会使用浏览器的F12功能
红线画出来的区域其实就是在搜索URL“http://so.ybdu.com/cse/search?”后面加的后缀(我对网页方面只是简单了解,所以用通俗的语言说),其中s和entry都是固定的,q后面则是我输入的“盘龙”的URL编码,以下是核心代码
base_url = 'http://so.ybdu.com/cse/search?'
name = raw_input('请输入你要寻找的电子书完整名称:')
headers = {'User-agent': 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0'}
data = urllib.urlencode({
'q':name,
's':'14402670595036768243',
'entry':'1'
})
real_url = base_url + data
req = urllib2.Request(real_url,headers=headers)
time.sleep(1)
#单次连接会出现错误,错误后休息1s后继续尝试连接
while True:
try:
rep = urllib2.urlopen(req)
break
except BaseException:
time.sleep(1)
html = rep.read()
使用到了urllib.urlencode、urllib2.Requesut和urllib2.urlopen函数,函数的具体功能如果不清楚可以自行百度
最后得到了搜索后界面的html代码
这里有个while True:… 这里是什么意思呢?
主要是如果只是单次打开的话,会出现Error 10054,百度了一番之后好像是超市问题,但是并没有找到合适的解决方法,就是用这种强制打开的方式,如果打开出错,就暂停1s之后继续打开,解决错误
Two
获取到搜索结束界面的HTML代码之后,需要将第一个搜索结果与输入的小说名字进行对比,如果成功则获取该小说的章节界面的URL进行下一步的访问,失败则提示返回。
下面是搜索网页的源代码
可以看到每一个搜索结果的名字在<a cpos="title"... ></a>
里面,所以直接提取出来做对比就OK
代码中使用的是bs4库中的Beautifulsoup函数
soup = BeautifulSoup(html,'html.parser')
sousuoname = soup.find(class_="result-game-item-title-link").get_text()
if cmp(str(sousuoname),name):
name = name+'.txt'
name = name.decode('utf-8')
filename = open(name,'a')
search_data(soup,filename)
filename.close()
else:
print '搜索失败'
Three
上一步获取了小说章节的URL,并且将URL和已经打开的文件传入search_data()函数,进一步抓取信息
分析网页源码可以知道每一章节其实在一个li中,而章节的网址就是<a href="140210.html">...</a>
href中再加上基础网址,就是你传入函数的URL
wenzhang_base_url = soup.find(class_="result-game-item-title-link")
href = re.compile(r'href="(.+?)"')
#找到小说章数页面 base url
wenzhang_base_url = re.findall(href,str(wenzhang_base_url))[0]
#访问小说页面 获取html
req = urllib2.Request(wenzhang_base_url,headers=headers)
html = urllib2.urlopen(req).read().decode('gbk').encode('utf-8')
#使用Beautifulsoup寻找每一章
soup1 = BeautifulSoup(html,'html.parser')
little_list = soup1.find('ul',class_='mulu_list')
little_list = re.findall(re.compile(r'<li>(.+?)</li>'),str(little_list))
for i in little_list:
href = re.compile(r'href="(.+?)"')
href = re.findall(href,i)
wenzhang_url = wenzhang_base_url + href[0]
#print wenzhang_url
fun(wenzhang_url,filename)
代码中的注释已经很清楚了,可能我写的有一部分可以用更简单的方法,大家自行摸索
Four
上一步找到了具体的每一章节,进行一个for循环,将每个章节的URL和文件传入fun()函数,就是进行具体的文章爬取
分析源码,可以看到每一章节的标题在<div class="hititle">
的<h1>
中,而文章则在<div id="htmlContent"....>
中,所以使用Beautifulsoup函数进行提取
headers = {'User-agent': 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0'}
req = urllib2.Request(url,headers=headers)
# 单次连接会出现错误,错误后休息1s后继续尝试连接
while True:
try:
rep = urllib2.urlopen(req)
break
except BaseException:
time.sleep(1)
html = rep.read()
soup = BeautifulSoup(html,'html.parser')
name = soup.find(class_="h1title").h1.get_text()
text = soup.find(class_="contentbox").get_text()
text = text.strip().split('
')[0].split()
这一部分最后两行可能不是一眼就能看明白的,所以大家尝试的时候可以进行分布来测试,可以方便理解
爬取到内容就是最后一步,将内容写入文件中
filename.write('************'+name.encode('gbk','ignore')+'**************'+'
')
for i in text:
filename.write(' '+ i.encode('gbk','ignore') +'
')
print '%s is ok' % name
time.sleep(0.25)
这里有使用encode函数的’ignore’参数,具体作用可以自行百度,如果不加的话,会出现Bug,我一开始也是不清楚这个参数,然后就懵逼了很久,网页的编码明明是’gbk’,为啥就会出现无法编译的错误,大家自己做的时候可以试一试,找找其中的感觉233333
好了,这就是我做的一个小说txt文件自动下载程序,只要你搜索的小说在这个网站中能搜到,就可以使用,如果有什么问题可以在评论里留言,我会尽力解答,我是个小菜鸡,希望可以交到互相学习的朋友,一起努力
由于爬取速度太慢,我有考虑到Requests库,于是又用requests爬一下,与之前做了下对比,分享给大家
最后两个版本的完整的代码在我的Github上面,urllib or urllib2 or requests
对scrapy爬虫框架有兴趣的小伙伴,可以了解下我的这篇博客,同样是实战篇。