https://www.zhihu.com/billboard/
在爬取一个网页的资料时,我们要先对网页的前端代码有一个初步的了解,有的时候我们需要的内容是内置js里面,那么用beautifulsoup来解析内容,就解析不到js里的内容,只能解析html里的
import requests
url='https://www.zhihu.com/billboard/'
html=requests.get(url)
print(html.text)
可以发现打印的内容是错误,是因为知乎有反爬虫机制,需要headers
headers={
'Cookie': '_zap=ac32394a-8928-4ab6-b353-a8c38d63c711; d_c0="AHAR10RN4hSPTiHG0clZ_edvgwcNXShdMNg=|1651564242"; Hm_lvt_98beee57fd2ef70ccdd5ca52b9740c49=1651564244; _xsrf=9e5cf534-08ec-4b43-9956-98a4ee7d80f5; KLBRSID=3d7feb8a094c905a519e532f6843365f|1651631163|1651630283; Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49=1651631162',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0'
}
导入Cookie和User-Agent即可模拟用户浏览器,同时因为复制下来的Cookie和User-Agent不是python的格式,所以要做成字典的格式,即key:value
所以要在前后加上单引号
import requests
from bs4 import BeautifulSoup
url = "https://www.zhihu.com/billboard/"
headers={
'Cookie': '_zap=ac32394a-8928-4ab6-b353-a8c38d63c711; d_c0="AHAR10RN4hSPTiHG0clZ_edvgwcNXShdMNg=|1651564242"; Hm_lvt_98beee57fd2ef70ccdd5ca52b9740c49=1651564244; _xsrf=9e5cf534-08ec-4b43-9956-98a4ee7d80f5; KLBRSID=3d7feb8a094c905a519e532f6843365f|1651631163|1651630283; Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49=1651631162',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0'
}
zhihuhtml = requests.get(url,headers=headers)
soup=BeautifulSoup(zhihuhtml.text,'lxml')
divs=soup.select('div .HotList-item')
for div in divs:
title=div.select('.HotList-itemBody .HotList-itemTitle')[0].text
print(title)
以上就可以打印出知乎热榜的50个标题
至于title为什么要加[0],初步理解为divtitle.select为一整个对象,是由很多列表组成,如果不加[0]就没法循环。
以后再来解释这一步。
接下来来爬取热搜的简介
通过观察html源文件,发现简介是存在于js里面。于是我们先找到一个简介的内容,然后用到正则表达式来匹配到简介的内容
”excerptArea”:{"text":"(简介内容)"}
大概是这样的一个结构。我们用惰性匹配(.*?)
来替代简介的文本内容
在findall一下全网页。这里的全网页是get请求得到的网页
最后for循环一一把结果打印
import re
re_intro=re.compile('"excerptArea":{"text":"(.*?)"},re.I|re.S')
result=re_intro.findall(zhihuhtml.text)
for r in result:
print('简介:',r)
re.I指不区分大小写,re.S表示包括所有字符
接下来爬取热榜文章的缩略图,因为有的文章没有缩略图,所以要做一个判断,
图片的src地址获取方式和获取标题是类似的
img=div.select('.Hotlist-itemImgContainer img')[0]['src']
再进行for循环即可
然后我们把爬取的图片都进行重新命名并且保存到本地文件夹里
需要注意的是,创建文件夹需要先导入os模块
判断文件夹是否存在,如果文件夹不存在,生成文件夹,然后把抓取的图片放入到文件夹里
图片从1.jpg开始生成
最后代码如下
import re
import os
import requests
from bs4 import BeautifulSoup
url = "https://www.zhihu.com/billboard/"
headers={
'Cookie': '_zap=ac32394a-8928-4ab6-b353-a8c38d63c711; d_c0="AHAR10RN4hSPTiHG0clZ_edvgwcNXShdMNg=|1651564242"; Hm_lvt_98beee57fd2ef70ccdd5ca52b9740c49=1651564244; _xsrf=9e5cf534-08ec-4b43-9956-98a4ee7d80f5; KLBRSID=3d7feb8a094c905a519e532f6843365f|1651631163|1651630283; Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49=1651631162',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0'
}
zhihuhtml = requests.get(url,headers=headers)
soup=BeautifulSoup(zhihuhtml.text,'lxml')
divs=soup.select('div .HotList-item')
for div in divs:
title=div.select('.HotList-itemBody .HotList-itemTitle')[0].text
print(title)
try:
img=div.select('.HotList-itemImgContainer img')[0]['src']
print(img)
if not os.path.exists('zhihu'):
os.mkdir('zhihu')
with open('zhihu/{}.jpg'.format(num),'wb')as f:
f.write(requests.get(img).content)
num+=1
except:
pass
re_intro=re.compile('"excerptArea":{"text":"(.*?)"}')
result=re_intro.findall(zhihuhtml.text)
for r in result:
print('简介:',r)