网页小说抓取 ios(一下python使用过程中可能遇到的小问题和爬取的简单思路)
优采云 发布时间: 2022-02-13 05:17网页小说抓取 ios(一下python使用过程中可能遇到的小问题和爬取的简单思路)
这次主要给大家分享一下python爬虫在使用过程中可能遇到的一些爬虫的小问题和简单的思路。
我自己不是程序员,python相关的内容也是自学的。如果您发现我的代码中有可以优化和改进的地方,请不吝赐教。即使是像我这样的普通新手,如果你找到更好的解决方案,也请分享,大家一起进步。
任务目标:
从 Tadu 文学的 网站 中获取小说并将其保存为 TXT 格式。
简单级应用,输入小说目录的URL,爬取所有内容。
程序流程图:
1、爬取小说目录网页信息
2、获取所有章节名称和链接
3、依次进入每一章的页面,抓取内容依次写入同一个txt文件
梦欣采用的技术:
1、urllib.request库-----操作url
2、循环中断,继续
3、时间库-------系统暂停
4、lxml库--------获取html代码中的指定内容
5、string.replace() 方法--------修改替换字符串的内容
6、用open()方法来操作文件
都是简单的技术,思路也比较简单,给大家做个参考。
首先是章节内容。通过DevTools可以发现文章内容在一个div中,整个html代码都有相关注释
那么复制xpath之后,任务就变成了获取[ //*[@id="partContent"] ]下所有P标签的内容,形成一个完整的章节内容。
我们开始简单,获取网页的内容,然后找到所有的章节文字,打印出来看看效果。
[Python] 纯文本查看
# -*- coding: utf-8 -*-
"""
Created on Wed Apr 7 15:32:39 2021
@author: roshinntou
"""
from lxml import etree
import urllib.request
import time
mainUrl = 'http://www.tadu.com'
def get_html_code(url):
max_count = 6
htmlcode = ''
for i in range(max_count):
print('No.'+str(i)+' start load:' + url)
try:
req_one = urllib.request.Request(url)
req_one.add_header('User-Agent', 'Mozilla/6.0')
res_one = urllib.request.urlopen(req_one, timeout=60)
htmlcode = res_one.read().decode('utf-8')
res_one.close()
break
except:
if i < max_count:
continue
else:
print('多次重复读取网页信息失败')
time.sleep(1)
return htmlcode
if __name__ == '__main__':
code = get_html_code('http://www.tadu.com/book/725327/86240835/')
html = etree.HTML(code)
text = html.xpath('//*[@id="partContent"]/p')
for i in text:
print(i.text)
这里,urllib.request 从获取html代码的过程中提取了一个方法。我将核心代码放入 for 循环并添加 try/catch 模块。如果一切正常,break 结束当前循环。如果报错,判断重复了多少次。,在指定次数内,使用 continue 重复执行核心代码,如果超过指定次数,会提示错误。(友情提示:由于网络波动或其他原因,爬取网页代码经常会超时,如果不添加循环方式,要么爬虫程序停止,要么爬取不到这部分的内容,影响最终结果.)
然后是内容处理。通过xpath,我们得到partContent div下的所有p标签,然后通过for循环打印出每个p标签的text文本。
但是执行的结果是:
读取html代码的模块不报错重复执行,只执行一次就结束。整个结果没有错误,证明至少所有的步骤都执行了,包括for循环,没有错误。没有超出下标等错误,也没有结果。for循环应该执行0次,没有得到P标签。
然后我们直接打印得到的html代码看看是怎么回事
结果发现:
如您所见,DIV 都找到了,但里面没有 文章 内容(红框位置)。所以没有错误,也没有执行结果。
然后它应该稍后动态加载。
刷新页面以查看网络内部的内容
然后我发现这个脚本有我们需要的
乱码需要重新编码为utf-8格式,回调是js的回调,所以网页代码中一定要有相关链接。我们打开网页的源码,搜索一下以“1462b”开头的东西看看:
可以看到这个输入的ID叫做bookPartResourceUrl,值里面的内容就是刚才的链接。那么我们在文章页面中获取这个链接的url地址,然后再次获取这个url地址的结果。主要方法的代码是:
[Python] 纯文本查看
if __name__ == '__main__':
code = get_html_code('http://www.tadu.com/book/725327/86240835/')
html = etree.HTML(code)
input_info = html.xpath('//*[@id="bookPartResourceUrl"]')[0].get('value')
code = get_html_code(input_info)
print(code)
第一步是获取这个页面的信息,然后找到input元素,获取它的value属性,得到一个url链接,然后再次读取这个链接的信息,结果是:
可以看到,两次浏览网页后,得到了文章的内容。每行内容都在一个 P 标签内。
此时,您可以通过多种方式使用它:
1、可以直接保存收录P标签的HTML代码,然后在网站中使用。
2、在保存txt的情况下,可以使用split的方式来'
'将这个内容截取成一个数组供目标使用,代码如下:
[Python] 纯文本查看
string.split('
')
3、我直接用replace方法,把'
' 替换为 '\n' 并且之前和之后的内容是固定的。直接截取string[22:-7]获取全部内容,然后直接写入txt文件即可。无需循环输入每个句子,性能消耗比较小
写法也很简单:
[Python] 纯文本查看
with open('网游:每十小时创造一个BUG.txt','a',encoding='utf-8') as file:
file.write('\n'+title+'\n')
file.write(text+'\n')
print('保存成功!')
使用with open的a模式,可以获取文件名作为参数传入,然后标题和内容换行,就可以连续写入同一个文件。现在主流的手机小说软件都是txt的,有多个切换*敏*感*词*不好。不要将每一章保存在单独的文件中。
到目前为止,我们已经能够根据章节 URL 获取章节的文本内容。接下来,我们需要一次性获取所有章节的标题和网址,然后依次读取所有章节并保存到一个txt文件中
先看目录结构:
它也是一个很简单的结构,每一章对应一个a标签。xpath 是 //*[@id="content"]/div[3]/div[2]/a
所以我们获取章节并进一步获取 文章 内容的方法应该是:
[Python] 纯文本查看
def get_all_url(url):
code = get_html_code(url)
print('get etree')
html = etree.HTML(code)
urlList = html.xpath('//*[@id="content"]/div[3]/div[2]/a')
for i in urlList:
title = i.text
title = title.replace(" ","").replace("\r\n","").replace(" ","").replace("\r","").replace("\n","")
url = i.get('href').replace(" ","").replace("\r\n","").replace(" ","").replace("\r","").replace("\n","")
print('title:'+title)
print('url:'+mainUrl+url)
get_text_by_url(mainUrl+url,title)
因为章节名前后有空格和换行符,所以我全部替换了。获取纯文本信息。
for循环就是将每一章的标题和URL传递给我们刚才做的保存内容的方法。
最后:
完整的代码是:
[Python] 纯文本查看
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 8 11:48:39 2021
@author: roshinntou
"""
from lxml import etree
import urllib.request
import time
mainUrl = 'http://www.tadu.com'
def get_html_code(url):
max_count = 6
htmlcode = ''
for i in range(max_count):
print('No.'+str(i)+' start load:' + url)
try:
req_one = urllib.request.Request(url)
req_one.add_header('User-Agent', 'Mozilla/6.0')
res_one = urllib.request.urlopen(req_one, timeout=60)
htmlcode = res_one.read().decode('utf-8')
res_one.close()
break
except:
if i < max_count:
continue
else:
print('多次重复读取网页信息失败')
time.sleep(1)
return htmlcode
def get_all_url(url):
code = get_html_code(url)
print('get etree')
html = etree.HTML(code)
urlList = html.xpath('//*[@id="content"]/div[3]/div[2]/a')
for i in urlList:
title = i.text
title = title.replace(" ","").replace("\r\n","").replace(" ","").replace("\r","").replace("\n","")
url = i.get('href').replace(" ","").replace("\r\n","").replace(" ","").replace("\r","").replace("\n","")
print('title:'+title)
print('url:'+mainUrl+url)
get_text_by_url(mainUrl+url,title)
def get_text_by_url(url,title):
code = get_html_code(url)
html = etree.HTML(code)
input_info = html.xpath('//*[@id="bookPartResourceUrl"]')[0].get('value')
print(input_info)
code = get_html_code(input_info)
#text = code[22:-7].split('
')
text = code[22:-7].replace('
', '\n')
with open('网游:每十小时创造一个BUG.txt','a',encoding='utf-8') as file:
file.write('\n'+title+'\n')
file.write(text+'\n')
print('保存成功!')
if __name__ == '__main__':
get_all_url('http://www.tadu.com/book/catalogue/743142')
#get_text_by_url('http://www.tadu.com/book/749916/91083959/','title')
每次执行时将小说的目录URL复制到get_all_url方法的参数中,然后在上面用open改文件名。
至此,我们通过目录URL成功获取了小说的所有信息。
如果Ta阅读被抓得太快,他将被禁止。请注意。
程序还有很大的改进空间:
1、输入书名,自动搜索下载功能比较简单,搜索到的小说链接就是一般页面链接
例如:这是一般的页面链接,但目录链接是固定的。在书和后面的id号之间加上目录,也就是拿到链接后可以自己拼接。
有网站这个搜索,参数隐藏在url中。直接搜索显示默认 url:
其实还是有投稿的
然后测试接口:
发现参数是参数
这样就可以直接查询和获取内容了。
2、多进程爬取。当前的代码需要很长时间才能下载一两千章的小说。您可以一起爬升多个进程。更简单的方法是单独下载它们,然后再将它们拼接在一起。或者使用协程处理。