Python从Web抓取信息(bs4,webbrowser,requests,selenium)

0.前言

本篇文章基于《Python编程从认知到实践》。在选取书籍中精华部分以外,还包含作者自身遇到的问题和解决方法。

1.简单的webbrowser模块示例程序

  • 从命令行参数或剪贴板中取得街道地址
  • 打开Web浏览器,指向该地址的页面
import webbrowser,sys,pyperclip
if __name__ == '__main__':
    if len(sys.argv)>1:
        address=' '.join(sys.argv[1:])
    else:
        address=pyperclip.paste()
webbrowser.open(address)

2.使用requests模块从Web下载文件

2.1下载一个网页示例

(base) PS C:\Users\20980> Conda activate pythonProject
(pythonProject) PS C:\Users\20980> python
Python 3.9.15 (main, Nov 24 2022, 14:39:17) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> res=requests.get('https://www.gutenberg.org/cache/epub/1112/pg1112.txt')
>>> type(res)
<class 'requests.models.Response'>
>>> res.status_code==requests.codes.ok
True
>>> len(res.text)
179380

2.2检查错误

  • 可以检查Response对象的status_code属性是否等于requests.codes.ok
  • 在Response对象调用raise_for_status()方法,下载失败则抛出异常(如果下载失败对于程序不算严重,可以使用try和except包裹这行代码)

3.将下载的文件保存到硬盘

在pycharm中运行这段代码:

import requests
if __name__ == '__main__':
    res = requests.get('https://www.gutenberg.org/cache/epub/1112/pg1112.txt')
    res.raise_for_status()
    playFile=open('D://story.txt','wb')
    for chunk in res.iter_content(100000):
        playFile.write(chunk)
    playFile.close()

结果:

过程解释:

  • 调用requests.get()下载文件
  • 'wb'调用open(),以写二进制的方式打开一个新文件(目的是保存文本中的万国码)
  • 利用Request对象的iter_content()方法做循环
  • 在每次迭代中调用write(),将内容写入该文件
  • 调用close()关闭该文件

4.HTML

5.用BeautifulSoup模块解析HTML

5.1从HTML创建一个BeautifulSoup对象

  • bs4.BeautifulSoup()函数调用时需要一个字符串,其中包含将要解析的HTML。bs4.BeautifulSoup()函数返回一个BeautifulSoup对象。
import requests,bs4
if __name__ == '__main__':
    res=requests.get('https://www.bilibili.com/')
    res.raise_for_status()
    noStarchSoup=bs4.BeautifulSoup(res.text, "html.parser")
    print(type(noStarchSoup))
  • 也可以向bs4.BeautifulSoup()传递一个File对象。

5.2用select()方法寻找元素

针对要寻找的元素,调用method()方法,传入一个字符串作为CSS选择器,这样就可以取得Web页面元素。(选择器就像正则表达式)

①:

import requests
if __name__ == '__main__':
    res=requests.get('https://www.apple.com.cn/')
    res.raise_for_status()
    text=open('D://text.txt','wb')
    for chunk in res.iter_content(100000):
        text.write(chunk)
    text.close()
import bs4
if __name__ == '__main__':
    exampleFile=open('D://text.html',encoding='utf-8')
    exampleSoup=bs4.BeautifulSoup(exampleFile.read(),'html.parser')
    elems=exampleSoup.select('div>span')
    for i in range (5):
        print(elems[i].getText())

输出:

+

搜索 apple.com.cn
取消



+

②:

5.3通过元素的属性获取数据

输入:

import bs4
if __name__ == '__main__':
    soup=bs4.BeautifulSoup(open('D://example.html'),'html.parser')
    spanElem=soup.select('span')[0]
    print(str(spanElem))
    print(spanElem.get('id'))
    print(spanElem.attrs)

输出:

<span id="author">Al Sweigart</span>
author
{'id': 'author'}

5.4实践

5.4.1关于headers()

5.4.1.1为什么要加上headers()

我们一般写的爬虫会默认向服务器发送爬取请求,而一般情况下网站是不允许被爬虫访问的,输出的text信息中会出现抱歉,无法访问等字眼。我们通过更改User-Agent字段则可以实现网站请求,实现网页应答。

5.4.1.2如何寻找headers()

  • 在要爬虫的网页中打开开发者工具
  • 点击网络,再点击文档
  • 找到标头,查看Request Headers的User-Agent字段,直接复制
  • 将刚才复制的User-Agent字段构造成字典形式

5.4.2开始实践

我们选取摄图网作为例子

5.4.2.1导入库

主要的库就是requests以及bs4BeautifulSoup

5.4.2.2寻找页面规律

由于这个网站查找图片时有翻页的操作,所以我们应该先弄清楚翻页时url变化的规律,不难看出,这个规律就是
url='https://699pic.com/soso/xihongshi-complex---------0--'+str(i)+'.html'

5.4.2.3网站结构分析:

进入这个网站,搜索我们想查找的图片,然后进入开发者界面观察,找到headers保存下来,作为爬虫的伪装。

然后观察,正确的图片链接在何处:
 

不难观察出,class值为lazyimg标签中,正确的图片链接就是data-original的值。

接下来,我们就可以准备写脚本下载目标图片了。

5.4.2.4完成程序

先放出整个程序:

#我们尝试下载西红柿图片的第一页和第二页

import requests
from bs4 import BeautifulSoup

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

def Save_Pics(page_begin,page_end):
    Total_Pics=0
    for i in range(page_begin,page_end):
        #根据要爬取的网站的翻页规律完成url的循环
        url='https://699pic.com/soso/xihongshi-complex---------0--'+str(i)+'.html'
        r=requests.get(url,headers=header)
        r.encoding='utf-8'
        if r.status_code==200:
            print('该页面请求成功,开始下载')
            page_content=r.text
            soup = BeautifulSoup(page_content, 'html.parser')
            tags = soup.find_all("img", class_='lazy')
            print('该页面有 ' + str(len(tags)) + '张图像')
            for tag in tags:
                print(tag)
                if tag['alt'] == '上海举报中心':
                    print('结束该页面的下载')
                else:
                    Total_Pics+=1
                    image = 'https:' + tag['data-original']
                    print(image)
                    fileName = 'D:\图片\西红柿/' + str(Total_Pics) + '.jpg'
                    r = requests.get(image, headers=header)
                    f = open(fileName, 'wb')
                    f.write(r.content)
                    f.close()
        else :
            print('请求失败,无法下载该页')
if __name__ == '__main__':
    Save_Pics(1,3)

打开文件夹,发现图片也按照标号保存完毕了:

在每一页的最后一个img标签中,是没有data-original的那个链接,这时已经进入到页面的末尾,因此需要加上一条判断。

6.用selenium模块控制浏览器

6.0准备工作:

6.0.1首先在环境中下载selenium

pip install selenium -i Simple Index

6.0.2安装火狐浏览器

默认安装在c盘比较好,后续操作就比较简单

6.0.3下载浏览器驱动

  • Firefox 浏览器驱动:Firefox
  • Chrome 浏览器驱动:Chrome
  • IE 浏览器驱动:IE
  • Edge 浏览器驱动:Edge
  • PhantomJS 浏览器驱动:PhantomJS
  • Opera 浏览器驱动:Opera

6.0.4设置环境变量

将驱动解压,分别放在对应环境中python.exe的路径中、火狐浏览器安装路径中。

然后将火狐浏览器的安装路径添加到系统环境变量中。

6.0.5测试

环境中运行下列代码:

from selenium import webdriver
if __name__ == '__main__':
    browser=webdriver.Firefox()

成功打开火狐浏览器即为成功。

6.1在页面中寻找元素

WebDriver对象有好几种方法用于在页面中寻找元素。

分为:findelement(返回第一个元素)和findelements(返回所有元素组成的)方法。

如果页面上没有元素匹配该方法要查找的元素,selenium模块就会抛出NoSuchElement异常。

简单的一个例子:

from selenium import webdriver
if __name__ == '__main__':
    browser=webdriver.Firefox()
    browser.get('https://699pic.com/')
    try:
        elem=browser.find_element_by_class_name('banxin bulletin')
        print('Found< %s>element with that class name!' %(elem.tag_name))
    except:
        print('Was not able to find an element with that name.')

但这个程序正常来说是可以找到这个元素的,但事实上并没有找到这个元素。

然后,我调查了一下,果然,这个库更新了,格式有所改动。。。

下面是新的格式:

from selenium import webdriver
from selenium.webdriver.common.by import By
if __name__ == '__main__':
    browser=webdriver.Firefox()
    browser.get('https://699pic.com/')
    try:
        elem=browser.find_element(By.CLASS_NAME,'index-header')
        print('Found< %s>element with that class name!' %(elem.tag_name))
    except:
        print('Was not able to find an element with that name.')

输出:

Found< div>element with that class name!

6.2点击页面

findelementfindelements返回的WebElement对象有一个click()方法:

from selenium import webdriver
from selenium.webdriver.common.by import By
if __name__ == '__main__':
    browser=webdriver.Firefox()
    browser.get('https://www.bilibili.com/')
    linkElem=browser.find_element(By.CLASS_NAME,'nav-search-btn')
    print(type(linkElem))
    linkElem.click()

上面这段程序完成进入bilibili网站,并且点击搜索按钮,完成事件。

6.3填写并提交表单

from selenium import webdriver
from selenium.webdriver.common.by import By
if __name__ == '__main__':
    browser=webdriver.Firefox()
    browser.get('https://www.bilibili.com/')
    linkElem=browser.find_element(By.CLASS_NAME,'nav-search-btn')
    SearchElem=browser.find_element(By.CLASS_NAME,'nav-search-input')
    SearchElem.send_keys('战鹰')
    linkElem.click()

6.4发送特殊键

针对不能用字符串值输入的键盘击键,这个模块解决了问题:selenium.webdriver.common.keys

由于这个模块名过长,因此我们一般在引入时,这么填写:from selenium.webdriver.common.keys import Keys

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
if __name__ == '__main__':
    browser=webdriver.Firefox()
    browser.get('https://www.bilibili.com/')
    SearchElem=browser.find_element(By.CLASS_NAME,'nav-search-input')
    SearchElem.send_keys('战鹰')
    SearchElem.send_keys(Keys.ENTER)

6.5点击浏览器按钮

四个方法:

browser.back()

browser.forward()

browser.refresh()

browser.quit()

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值