基于requests_html的爬虫实战

爬取博客园首页科技新闻的前10篇标题+链接试试手

网址为推荐新闻 - 科技新闻 - 博客园

代码如下

python 复制代码
from requests_html import HTMLSession
session=HTMLSession()
r=session.get('https://news.cnblogs.com/n/recommend')
r.html.render()
all_news=r.html.find('h2.news_entry>a')
for news in all_news[:11]:
    print(news.text,'https://news.cnblogs.com/n/recommend'+news.attrs['href'])

r.html.find('h2.news_entry>a') 的含义是查找所有class属性为'news_entry'的<h2>标签,并返回它的直接子元素<a>标签,注意'>'表示选择直接子元素,外面不能嵌套着其它标签

输出如下

尝试保存5张python图标到一个自建文件夹中

后面的图片有Base64 编码的,要解码处理,就不爬了

url为python图标 - 搜索 图片

提示,图片是在<img>标签中,我们把属性src的链接提取下来,再使用requests.get(url)获取图片内容

这种有规律的网页其实用xpath方法搜索很方便,以下为两张图片<img>的xpath

python 复制代码
/html/body/div[4]/div[5]/div/div[1]/ul[1]/li[1]/div/div[1]/a/div/img
/html/body/div[4]/div[5]/div/div[1]/ul[1]/li[2]/div/div[1]/a/div/img

我本想用这个规律,可是这样就搜索不到了,可能是因为绝对 XPath 很容易因为页面结构的变化而失效,所以建议使用相对 XPath,可以更灵活地定位元素(哦哦哦!主包后期试过了,复制XPath可以爬取到,这个就是相对的,如//*[@id="mmComponent_images_1"]/ul[1]/li[1]/div/div[1]/a/div/img)。当然了,搜索方法很多,大家选择自己喜欢的就好~

代码如下

python 复制代码
from requests_html import HTMLSession
import os

os.makedirs('python_icons')  #在Python脚本运行的当前工作目录下创建一个文件夹
session=HTMLSession()
r=session.get('https://cn.bing.com/images/search?q=python%E5%9B%BE%E6%A0%87&form=HDRSC2&first=1&cw=1177&ch=723')
r.html.render()
imgs=r.html.xpath('//div[@class="img_cont hoff"]/img')
for i in range(5):
    url=imgs[i].attrs['src'] 
    r=session.get(url)
    if r.status_code!=200:
        continue                                          #python_icons/是文件夹路径,'第{i+1}张'是文件名,.png是文件扩展名,表示图片
    with open(f'python_icons/第{i+1}张.png','wb') as f:   #with open()是Python中用于打开文件的管理器,它确保文件在操作完成后会自动关闭
       f.write(r.content)                                 #wb以二进制写入模式打开文件,图片要用二进制写入,r.content返回响应的二进制内容
session.close()

展示如下,在文件目录可以看到,确实是在"python_icons"文件夹

爬取实习僧平台3个职位招聘信息制作成多表单

网址实习僧|大学生实习|校招求职|校园招聘

接下来我将爬取"产品经理""架构师""运维工程师"这3个职位招聘信息的岗位名称、薪资、城市的数据(为了减少运行时间,我每种职位只爬取一页数据)

提示,可以观察到,每种职位的url只是keyword不同,所以我们只需要修改keyword就能访问不同职位的招聘网页

不知道大家能否成功爬取数据呢?开始我想在外页面(如下)直接爬取,改了好几遍代码都不行,还是只能先获取招聘广告的链接再获取信息了。

代码如下

python 复制代码
from requests_html import HTMLSession
import pandas as pd                #把标准库/第三方库pandas起别名pd
import urllib.parse

session=HTMLSession()
headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0'}

def getinfo(n_url):
    r=session.get(n_url,headers=headers)
    r.html.render()
    name=r.html.find('div.new_job_name')[0].text
    salary=r.html.find('div.job_msg')[0].find('span')[0].text
    city=r.html.find('div.job_msg')[0].find('span')[1].text
    return [name,salary,city]
    
def getLinks(ul):
    info=[]
    r=session.get(ul,headers=headers)
    r.html.render()
    items=r.html.find('div.intern-wrap.interns-point.intern-item')
    for item in items:
        nurl=item.find('a')[0].attrs['href']
        info.append(getinfo(nurl))    #注意不是data+=,+=会把列表里的3个字符串当成3个独立元素追加,最终得到的是一维列表
    return info
        
jobs=["产品经理","架构师","运维工程师"]
columns=['职位名称','薪资','城市']
with pd.ExcelWriter('job_posting.xlsx', engine='openpyxl', mode='w') as writer:   #with ... as ...上下文管理器,会把打开和关闭这两步自动帮你完成
    for job in jobs:                                                              #'job_posting.xlsx'是最终文件名,engine='openpyxl'是后端引擎,mode='w'表示覆盖写模式
        ejob=urllib.parse.quote(job)               #把中文字符转为URL百分号编码
        url=f"https://www.shixiseng.com/interns?keyword={ejob}&city=%E5%85%A8%E5%9B%BD&type=intern&from=menu"
        informs=getLinks(url)
        df=pd.DataFrame(informs,columns=columns)   #用二维列表和列名创建DataFrame对象
        df.to_excel(writer, sheet_name=job, index=False)     #.to_excel()方法,把DataFrame里的二维表格数据,写进一个Excel文件里的工作表(Sheet)

输出展示如下

结语

爬取数据后还要清洗数据、可视化数据可以的话还可以加上GUI设计,这样才是一个完整的爬虫应用,后面的步骤比较笼统,我就不演示介绍了。还有分享或者想了解的技术欢迎在评论区留言,爬虫这块暂时结束了。

最后分享一下格式化字符串的方法

python 复制代码
# .format()方法,使用{}作为占位符,将值插入到字符串中
name="Alice"
age=25
message="My name is {} and I am {} years old.".format(name,age)     
print(message)
# <左对齐  >右对齐  ^居中对齐
# 可以指定占位符的宽度(默认以空格填充);对于浮点数,可以指定小数点后的位数
print("{:>10}".format("Hello"))    # 输出:     Hello
print("{:.2f}".format(3.14159))    # 输出:3.14
print("{:10.2f}".format(3.14159))  # 输出:      3.14
python 复制代码
#f-string字符串格式化方法,使用前缀f或F,在字符串中直接嵌入表达式
name="Alice"
age=25
message=f"My name is {name} and I am {age} years old."
print(message)
#格式化选项与.format()相似
print(f"{name:^10}")     # 居中对齐,宽度为10
print(f"{3.14159:.2f}")  # 输出:3.14

附带分享一些快捷键

CTRL+C,复制选取文字

CTRL+V,粘贴复制的文字

CTRL+A,选中全部

CTRL+Z,撤销上一步