知乎热榜爬取

2022-05-17 677 0

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)

相关文章

Tkinter学习(2)
Tkinter学习(1)
selenium自动化模块学习(5)
selenium自动化模块学习(4)
selenium自动化模块学习(3)
selenium自动化模块学习(2)

发布评论