emm……真实的高三暑假是,整天无事可做然后找事,于是开始学习Python
由题,作为一名初学者,想要玩转爬虫这类玩意还要花很大功夫。
所以我就从简单的开始:提取XKCD漫画(网页简单,提取方便)
使用 requests 和 bs4 模块提取网页内容+分析html,然后再存入硬盘内
首先,requests 和 bs4 都是 Python 的第三方库,使用 pip install xxx(xxx 是 requests 和 bs4)安装它们
requests 库最主要的方法是 requests.get(),根据指定的 url 提取超链接指向的内容,可以附带其他的一些参数来达到特定的目的
比如,传入 timeout = 10 可以使得 连接和读取超时的时间为 10s,超时会报错
(用法:get(url, params=None, **kwargs),**kwargs为可变参数,包含了timeout等)
这个网站很慢而且不稳定,时常有连接不上的问题,为了防止爬虫卡死,加入了重试的代码:
import requests, bs4
url = "http://xkcd.com"
downloadCount = 0 # 下载的图片文件计数
def get_elements(link, tle=10): # tle:超时时间
count = 1 # count:尝试访问网页的次数
# 访问成功则返回requests.get()取得的值,超过3次失败则抛出异常
while count <= 3:
try:
res = requests.get(link, timeout=tle)
res.raise_for_status()
return res
except requests.exceptions.RequestException:
count += 1
print("Connection timeout. Retry --> %d in 3 times..." % count)
raise TimeoutError("Your network is really bad. Please check your Internet and try again later.")
(其实可以由 requests 已经封装好的代码来操作……然而暂时先不这么做)
就可以用 bs4.BeautifulSoup() 来分析这个网页的 html 了
马上找到图片的链接,然后下载这个图片
soup = bs4.BeautifulSoup(res.text,features="html.parser") # 解析html,找到漫画图片对应的链接
releventContent = soup.select("#comic img") # 图片都在html的这一段之内
picUrl = releventContent[0].get("src")
print("Downloading picture %d..." % downloadCount) # 下载图片
picResource = get_elements("http:" + picUrl)
每一张漫画都有对应的编号,存入硬盘时,为了更好区分,于是写入文件时就以 编号+漫画标题 的方式写入
prevUrl = soup.select("a[rel='prev']") # prevUrl = '/1234/' 查找图片编号;格式如左
prevNum = prevUrl[0].get("href")
currentNum = 0 # 查找到当前图片的编号
if prevNum == '#':
currentNum = 1
else:
currentNum = int(prevNum.strip('/')) + 1
print("Writing picture %d..." % downloadCount) # 文件写入硬盘
picFile = open(str(currentNum) + '_' + os.path.basename(picUrl), 'wb')
# 以 编号+标题 的方式命名,二进制方式写入
for c in picResource.iter_content(100000): # 写入文件
picFile.write(c)
picFile.close()
print("File %d successfully written." % downloadCount)
最后别忘了调整 url 为上一幅漫画的:
url = "http://xkcd.com" + prevNum # 上一幅图片的url
图例:
并不规范的源码:
#! python3
# 爬虫实践1:XKCD Comics
# reversed sequence of comics, from latest to 1st image.
import os
import requests,bs4
os.chdir("g:\\work\\gjmtest\\comics")
os.makedirs("xkcd",exist_ok=True)
os.chdir(".\\xkcd")
url = "http://xkcd.com/"
downloadCount = 0
def get_elements(link, tle=10):
count = 1
while count <= 3:
try:
res = requests.get(link, timeout=tle)
res.raise_for_status()
return res
except requests.exceptions.RequestException:
count += 1
print("Connection timeout. Retry --> %d in 3 times..." % count)
raise TimeoutError("Your network is really bad. Please check your Internet and try again later.")
while not url.endswith('#'):
downloadCount += 1 # 下载的文件总数
if downloadCount > 50:
break
print("Analyzing page %d..." % downloadCount)
res = get_elements(url)
soup = bs4.BeautifulSoup(res.text,features="html.parser") # 解析html,找到漫画图片对应的链接
releventContent = soup.select("#comic img")
picUrl = releventContent[0].get("src")
print("Downloading picture %d..." % downloadCount) # 下载图片
picResource = get_elements("http:" + picUrl)
prevUrl = soup.select("a[rel='prev']") # prevUrl = '/1234/' 查找图片编号;格式如左
prevNum = prevUrl[0].get("href")
currentNum = 0 # 查找到当前图片的编号
if prevNum == '#':
currentNum = 1
else:
currentNum = int(prevNum.strip('/')) + 1
print("Writing picture %d..." % downloadCount) # 文件写入硬盘
picFile = open(str(currentNum) + '_' + os.path.basename(picUrl), 'wb')
# 以 编号+标题 的方式命名,二进制方式写入
for c in picResource.iter_content(100000): # 写入文件
picFile.write(c)
picFile.close()
print("File %d successfully written." % downloadCount)
url = "http://xkcd.com" + prevNum # 上一幅图片的url
print("Done.")