前言
一直想学爬虫来着,做做脚本什么的,还顺路还可以学点html基础,扩展点技术栈,以下是自己做的笔记和实践,
目前看的是 这个 ,关于爬虫的一个比较入门的视频,主要的学到的库有 requests re bs4 后面的scrapy感觉讲的泛泛没有仔细看,都用 pip intall requests
安装即可,re库是python标准库不用额外安装。
主要是非动态生成的网页爬取,并且只爬取html页面信息,如果有关数据封在了json里那搞不定
说白了就是一些字符串的分析,结合了re或者利用bs4帮助分析。
Requests 库
模拟用户行为向服务器发送请求,主要函数就是requests.method() 有七个method函数,常用的就get和head两种,我觉得delete很有意思,应该不会有哪个缺心眼的允许用户可以随意更改自己html上的资源吧,几个方法其实都是都是request方法封装的,可以直接调用request方法然后第一个传参写一下就好,但我觉得麻烦。
上一个图:
贴一个标准爬取的模板,用try except结构保证异常不跳出,也可以自己if检查request.status(),如果状态码不是200那就是有问题,但是这方法不如tryexcept结构
def template_get():
try:
user_agent={'user-agent':'Chrome/10'}
search = {'k':'xbox'}
web = requests.get(headers=user_agent,url=r'https://www.amazon.de/s',params=search)
web.raise_for_status()
web.encoding=web.apparent_encoding #这段的意思是把信息的解码方式定义一下,否则可能会出现无法正常显示的字符
#一般来说apparent encoding比较准
return web.text
except:
return 'ERROR'
另外这个用到了get
里关于params
和head
的应用,
1.headers
重写了申请里关于设备user_agent
的描述,简单的绕过了反爬
2.params
参数则加上了上边定义的search
键值对,达到了对url
的扩充,从而实现搜索功能,因为亚马逊的搜索api是/s
, 同理要爬取的网页可以看一看对应的搜索api是什么
3.web.encoding=web.apparent_encoding
这一句对一些已知的网页,或者同时爬取某个网站同类型网页时,可以提前查看下,或者先爬一个网页知道解码方式,后续可以手动指定来获取更快的解析速度,因为apparent_encoding方法会对text解析,耗时会“”较长"
4.就是网页的html内容,即源代码,如果需要爬取的内容在这里面可以考虑使用bs4库继续html语法结构解析或者用re库使用正则表达式直接匹配,或者两个结合使用,反正就是对文本的筛选和分析
再一个比较常见的例子,爬图片
def template_getImage():
try:
user_agent = {'user-agent': 'Chrome/10'}
path = './saved.jpg'
web = requests.get(headers=user_agent,
url=r'https://blob.keylol.com/forum/202109/11/233847wk2iuua26oo0i8i8.jpg')
web.raise_for_status()
web.encoding = web.apparent_encoding
with open(path, 'wb') as f:
f.write(web.content)
except:
return 'ERROR'
这个例子主要是用到了返回的request对象下content属性,用request库返回的对象有很多属性,比如上个例子的text,这个就用到了内容属性,也就是二进制的东西,把它写成图片,因为有后缀名限定,并且content的内容里也有关于jpg编码的东西,可以打印看看
bs4 库
自己写一个爬取当前页面所有图片的demo来介绍下bs4库
def getHTMLtext(url):
try:
user_agent = {'user-agent': 'Chrome/10'}
search = {'k': 'xbox'}
web = requests.get(headers=user_agent, url=url)
web.raise_for_status()
web.encoding = web.apparent_encoding
return web.text
except:
return 'ERROR'
def savetImage(image_url):
try:
user_agent = {'user-agent': 'Chrome/10'}
name = image_url.split('/')[-1]
prefix, sufix = name.split('.')[-2], name.split('.')[-1][:3]
path = f'./{prefix}.{sufix}'
web = requests.get(headers=user_agent,
url=image_url)
web.raise_for_status()
web.encoding = web.apparent_encoding
with open(path, 'wb') as f:
f.write(web.content)
return 'Done'
except:
return 'ERROR'
def template_getImage2(text):
soup = BeautifulSoup(text, 'html.parser')
for link in soup.find_all('img'):
image_url = link.get('file')
if image_url is None:
continue
try:
print(savetImage(image_url))
except:
print(f'ERROR AT {image_url}')
if __name__ == '__main__':
url = r'https://keylol.com/t748192-1-1'
if url
demo = getHTMLtext(url)
if demo !='ERROR':
template_getImage2(demo)
首先看一眼源码发现楼里的图都在img这个标签下,再具体一点就是img下的file键值对,分析完毕就好办了,大概流程如此:
(获取源码即requests库的东西,不赘述)
首先摘出来所有img标签: for link in soup.find_all('img'):
接着提取里面的键值对: image_url = link.get('file')
然后分析名字用原名保存 : prefix, sufix = name.split('.')[-2], name.split('.')[-1][:3]
别忘了加一些异常判断保证遇到空或者出错时程序不跳出
优化一下
可以看到这个帖子有好多页,怎么实现自动翻页功能呢?首先肯定是要对帖子链接'https://keylol.com/t748192-1-1'
进行分析
很容易的我们发现这个帖子页数是根据最后-1-1
进行储存的那这就好办了,很快啊,就想到一个很直接的思路:
爬完一页然后尝试爬下一页
行就爬,不行就中断结束
具体操作为:
if __name__ == '__main__':
url_prefix = r'https://keylol.com/t748192'
page_nr = 1
page_limt = 999
while page_limt > page_nr:
page = f'-{page_nr}-1'
url = url_prefix + page
print(url)
demo = getHTMLtext(url)
if demo != 'ERROR':
template_getImage2(demo)
page_nr += 1
else:
print('end')
break
除此之外也可以在request.get函数中更改param的值,都是一样的