【Python爬虫】第三课 网页爬取

4 篇文章 1 订阅
订阅专栏

静态网页是网站建设的基础,早期的网站基本都是由静态网页构成的。静态网页通常为纯粹的HTML格式,也可以包含一部分动态效果,如GIF格式的动画,Flash,滚动字幕等,该类网页的文件扩展名为.htm,.html。静态网页通常没有后台数据库,页面不含有程序并且无法交互。静态网页无法实时更新,更新页面时需要重新发布,通常适用于更新较少的展示型网站。本章将分别使用urllib3库,Requests库向网站发送HTTP请求并获取响应内容,再分别使用Chrome开发者工具,正则表达式,Xpath和Beautiful Soup解析获取的网页内容,最后将解析后的结果分别用Json模块,PyMySQL库进行存储。

3.1 实现HTTP请求

一个爬虫的基本功能是读取URL和抓取网页内容,这就需要爬虫具备能够实现HTTP请求的功能。请求过程包括生成请求,请求头处理,超时设置,请求重试,查看状态码等。分别通过urllib3库,Requests库实现向网站发送GET类型的HTTP请求,并获取返回的响应。

使用urllib3库实现

许多Python的原生系统已经开始使用urllib3库,其提供了很多python标准库里所没有的重要特性。

连接特性连接特性
线程安全管理连接池
客户端SSL∕TLS验证使用分部编码上传文件
协助处理重复请求和HTTP重定位支持压缩编码
支持HTTP和SOCKS代理测试覆盖率达到100%

urllib3库的下载和安装

按住window+R键,在弹出的搜索框中输入cmd,打开dos窗口

 输入指令,使用pip下载urllib3库

已下载完成,在pycharm开发软件中查看该第三方库是否下载完毕。

在系统设置中能看到我们下载好的urllib3库,说明就下载好了

接着就能直接使用了。

1. 生成请求

通过request方法即可创建一个请求,该方法返回一个HTTP响应对象。request语法格式如下。

urllib3.request(method,url,fields=None,headers=None,urlopen_kw)

reques方法常用的参数及其说明如下。

参数说明
method接收string。表示请求的类型,如“GET”、“HEAD”、“DELETE”等。无默认值
url接收string。表示字符串形式的网址。无默认值
fields接收dict。表示请求类型所带的参数。默认为None
headers接收dict。表示请求头所带参数。默认为None
urlopen_kw接收dict或其他Python中的类型的数据。依据具体需要及请求的类型可添加的参数,通常参数赋值为字典类型或为具体数据。无默认值

那我们通过代码来演示效果:

# 导入urllib3库
import urllib3
# 创建PoolManager对象
http=urllib3.PoolManager()
# 通过调用request方法使用get请求访问该网站地址
rq=http.request("GET","http://www.tipdm.com/tipdm/index.html")
# 查看服务器响应码
print("服务器响应码:",rq.status)
# 服务器响应码: 200
# 查看响应实体 将页面内容从字节按UTF-8编码格式进行编码输出
print("获得网页源代码:",rq.data.decode("UTF-8"))

 运行结果如下:

通过获取的源码可以和网页的查看源代码进行对比是否是一致的。那么这就是爬虫的强大。  

2. 请求头处理

在request方法中,如果需要传入headers参数,可通过定义一个字典类型实现。定义一个包含User-Agent信息的字典,使用浏览器为火狐和chrome浏览器,操作系统为“Windows NT 6.1; Win64; x64”,向网站发送带headers参数的GET请求,hearders参数为定义的User-Agent字典。

# 防止服务器察觉爬虫的爬取,进行伪装成真实浏览器访问服务器地址
import urllib3
# 设置浏览器访问请求头信息
ua={"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"}
http=urllib3.PoolManager()
#使用Get请求访问地址,并携带请求头信息
rq=http.request("GET","http://www.tipdm.com/tipdm/index.html",headers=ua)
print(rq.status)
print(rq.data.decode("UTF-8"))

浏览器是通过User-Agent参数来判断是正常用户的访问,还是非正常用户的访问。因此我们使用爬虫的时候,避免浏览器拦截我们的爬虫请求的情况下,需要加上请求头参数访问地址。

3. Timeout设置

为防止因为网络不稳定、服务器不稳定等问题造成连接不稳定时的丢包,可以在请求中增加timeout参数设置,通常为浮点数。依据不同需求,timeout参数提供多种设置方法,可直接在URL后设置该次请求的全部timeout参数,也可分别设置该次请求的连接与读取timeout参数,在PoolManager实例中设置timeout参数可应用至该实例的全部请求中。

# 在爬取服务器网页代码时,
# 可能因为网络不稳定而导致爬取的数据不完整
# 因此根据需求设置爬取数据TimeOut超时参数信息
import urllib3
#方式一
url="http://www.tipdm.com/tipdm/index.html"
http=urllib3.PoolManager()
rq=http.request("GET",url,timeout=3.0)
#方式二
#对于超时参数的详细设置,这里设置连接服务器时间为1秒,读取数据时间位3秒
rq=http.request("GET",url,timeout=urllib3.Timeout(connect=1.0,read=3.0))

#方式三
http=urllib3.PoolManager(timeout=4.0)
#方式四
http=urllib3.PoolManager(timeout=urllib3.Timeout(connect=1.0,read=3.0))
print(rq.status)
print(rq.data.decode("UTF-8"))

需要注意的是:如果已经在PoolManager对象中设置了timeout参数,则之后在request方法中另行设置的timeout参数将会替代PoolManager对象中的timeout方法。

4.请求重试设置

urllib3库可以通过设置retries参数对重试进行控制。默认进行3次请求重试,并进行3次重定向。自定义重试次数通过赋值一个整型给retries参数实现,可通过定义retries实例来定制请求重试次数及重定向次数。若需要同时关闭请求重试及重定向则可以将retries参数赋值为False,仅关闭重定向则将redirect参数赋值为False。与Timeout设置类似,可以在PoolManager实例中设置retries参数控制全部该实例下的请求重试策略。

# 设置爬取指定网页地址的访问次数
# 网络不稳定或者爬取失败的情况下,重复性爬取
import urllib3

#方式一
#设置访问指定地址的次数为5次,重新尝试访问5次
http=urllib3.PoolManager(retries=5)
#同时设置重定向访问
#表示设置尝试连接的次数为5次,尝试读取数据的次数为4次
http=urllib3.PoolManager(timeout=urllib3.Retry(5,read=4))

#方式二
http=urllib3.PoolManager()
url="http://www.tipdm.com/tipdm/index.html"
#设置重新尝试访问连接次数10次
rq=http.request("GET",url,retries=10)
#设置连接次数5次,读取数据次数4次
rq=http.request("GET",url,retries=5,redirect=4)

#关闭重复访问,关闭重复读取
rq=http.request("GET",url,retries=False,redirect=False)

5. 生成完整HTTP请求

使用urllib3库实现生成一个完整的请求,该请求应当包含链接、请求头、超时时间和重试次数设置。

# 使用urllib3库爬取网页源代码
import urllib3
#定义要爬取的网址
url="http://www.tipdm.com/tipdm/index.html"
#设置访问服务器的请求头参数
ua={"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"}
#设置访问超时时间参数信息
to=urllib3.Timeout(connect=1.0,read=3.0)
#设置重新尝试访问次数和读取数据的次数,并生成请求
http=urllib3.PoolManager()
rq=http.request("GET",url,headers=ua,timeout=to,retries=5,redirect=4)
#获取状态码
print(rq.status)
#获取爬取的网页源代码
print(rq.data.decode("UTF-8"))

使用requests库实现

requests库是一个原生的HTTP库,比urllib3库更为容易使用。requests库发送原生的HTTP 1.1请求,无需手动为URL添加查询字串,也不需要对POST数据进行表单编码。相对于urllib3库,requests库拥有完全自动化Keep-alive和HTTP连接池的功能。requests库包含的特性如下。

连接特性连接特性连接特性
Keep-Alive&连接池基本∕摘要式的身份认证文件分块上传
国际化域名和URL优雅的key∕value Cookie流下载
带持久Cookie的会话自动解压连接超时
浏览器式的SSL认证Unicode响应体分块请求
自动内容解码HTTP(S)代理支持支持.netrc

该库也是第三方库,需要通过pip进行下载和安装,这里的操作过程就不再重复了,按照urllib3库的下载操作执行一遍即可。

1. 生成请求

requests库生成请求的代码非常便利,其使用的request方法的语法格式如下。

requests.request.method(url,**kwargs)

request方法常用的参数及其说明如下。

参数说明
method接收string。表示请求的类型,如“GET”、“HEAD”、“DELETE”等。无默认值
url接收string。表示字符串形式的网址。无默认值
**kwargs接收dict或其他Python中的类型的数据。依据具体需要及请求的类型可添加的参数,通常参数赋值为字典类型或为具体数据
# 使用requests爬取指定的网页源代码
import requests
url="http://www.tipdm.com/tipdm/index.html"
# 通过get请求进行爬取该网址的数据 get:获得(从网上下载数据)
# post:提交(将数据上传到服务器)
reg=requests.get(url)
#查看当前对象的数据类型
print("结果类型:",type(reg))
#查看连接的状态码
print("状态码:",reg.status_code)
#查看网页源代码的编码格式
print("查看编码格式:",reg.encoding)
#修改编码格式
#reg.encoding="GBK"
#print("改变后的编码格式:",reg.encoding)
#获得该网页的响应头信息
print("响应头:",reg.headers)
#获得该网页的源代码
print("网页源代码:",reg.text)

在以上代码中Requests库仅用一行代码便可生成GET请求,操作比urllib3库简洁。

2. 查看状态码与编码

需要注意的是,当requests库猜测错时,需要手动指定encoding编码,避免返回的网页内容解析出现乱码。

url = 'http://www.tipdm.com/tipdm/index.html'
rqg = requests.get(url)
print("状态码:", rqg.status_code)   # 查看状态码
print("编码:", rqg.encoding)     # 查看编码
rqg.encoding  = 'GBK'  # 手动指定编码
print("修改后的编码:", rqg.encoding)     # 查看修改后的编码

手动指定的方法并不灵活,无法自适应对应爬取过程中不同网页的编码,而使用chardet库比较简便灵活,chardet库是一个非常优秀的字符串∕文件编码检测模块。(需要先下载该库)

chardet库使用detect方法检测给定字符串的编码,detect方法常用的参数及其说明如下。

参数说明
byte_str接收string。表示需要检测编码的字符串。无默认值
import chardet
url = 'http://www.tipdm.com/tipdm/index.html'
rqg = requests.get(url)
print("编码:", rqg.encoding)     # 查看编码
print("detect方法检测结果:", chardet.detect(rqg.content))
rqg.encoding = chardet.detect(rqg.content)['encoding']  # 将检测到的编码赋值给rqg.encoding
print("改变后的编码:", rqg.encoding)     # 查看改变后的编码

3. 请求头与响应头处理

requests库中对请求头的处理与urllib3库类似,也使用headers参数在GET请求中上传参数,参数形式为字典。使用headers属性即可查看服务器返回的响应头,通常响应头返回的结果会与上传的请求参数对应。

url = 'http://www.tipdm.com/tipdm/index.html'
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) Chrome/65.0.3325.181'}
rqg = requests.get(url,headers = headers)
print("响应头:", rqg.headers)      # 查看响应头

响应头: {'Server': 'nginx', 'Date': 'Wed, 10 Aug 2022 08:05:51 GMT', 'Content-Type': 'text/html; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'ETag': 'W/"15693-1585297141000"', 'Last-Modified': 'Fri, 27 Mar 2020 08:19:01 GMT', 'Content-Encoding': 'gzip'}

4. Timeout设置

为避免因等待服务器响应造成程序永久失去响应,通常需要给程序设置一个时间作为限制,超过该时间后程序将会自动停止等待。在requests库中通过设置timeout这个参数实现,超过该参数设定的秒数后,程序会停止等待。

# 使用Reuqests设置响应头信息模拟浏览器访问服务器
import requests
url="http://www.tipdm.com/tipdm/index.html"
headers={"user-agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"}
#reg=requests.get(url,headers=headers)
reg=requests.get(url,timeout=2.0)
print("获得模拟真实浏览器访问的网页响应头信息:",reg.headers)

5. 生成完整HTTP请求

使用requests库的request方法向网站发送一个完整的GET请求,该请求包含链接、请求头、响应头、超时时间和状态码,并且编码应正确设置。

import chardet
# 设置url
url = 'http://www.tipdm.com/tipdm/index.html'
# 设置请求头
headers= {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) Chrome/65.0.3325.181'}
# 生成GET请求
rqg = requests.get(url, headers = headers, timeout=2)
print("状态码:", rqg.status_code)   # 查看状态码
print("编码:", rqg.encoding)     # 查看编码
# 修正编码
rqg.encoding = chardet.detect(rqg.content)['encoding']
print("修改后的编码:", rqg.encoding)     # 查看修改后的编码
print("响应头:", rqg.headers)      # 查看响应头
print(rqg.text)         # 查看网页内容

3.2 解析网页

通过解析网页可以获取网页包含的数据信息,如文本,图片,视频等,这需要爬虫具备定位网页中信息的位置并解析网页内容的功能。通过Chrome开发者工具直接查看网站的页面元素,页面源码和资源星系信息,分别通过正则表达式,Xpath及Beautiful Soup解析通过Requests库获取的网站的页面内容,获取其中的元素及相关信息。

使用chrome开发者工具查看网页

chrome浏览器提供了一个非常便利的开发者工具,供广大web开发者使用,该工具提供包括查看网页元素、查看请求资源列表、调试JS等功能。该工具其中一个打开方式可通过右键单击chrome浏览器页面,在弹出菜单中单击图所示的“检查”选项打开。

也可以单击chrome浏览器右上角快捷菜单,如图所示,单击“更多工具”选项中的“开发者工具”选项,或使用快捷键组合Ctrl+Shift+I。  

chrome开发者工具目前包括了9个面板,界面如图所示。  chrome开发者工具各面板功能如下。

面板说明
元素面板(Elements)该面板可查看渲染页面所需的HTML、CSS和DOM(Document Object Model)对象,并可实时编辑这些元素调试页面渲染效果
控制台面板(Console)该面板记录各种警告与错误信息,并可作为shell在页面上与JavaScript交互
源代码面板(Sources)该面板中可以设置断点调试JavaScript
网络面板(Network)该面板可查看页面请求、下载的资源文件及优化网页加载性能。还可查看HTTP的请求头、响应内容等
性能面板(Performance)原旧版chrome中的时间线面板(Timeline),该页面展示页面加载时所有事件花费时长的完整分析
内存面板(Memory)原旧版chrome中的分析面板(Profiles),提供比性能面板更详细的分析,如可跟踪内存泄露等
应用面板(Application)原旧版chrome中的资源面板(Profiles),该面板可检查加载的所有资源
安全面板(Security)该面板可调试当前网页的安全和认证等问题并确保网站上已正确地实现HTTPS
审查面板(Audits)该面板对当前网页的网络利用情况、网页性能方面进行诊断,并给出优化建议

对于爬虫开发来说,常用的面板为元素面板,源代码面板和网络面板。

使用正则表达式解析网页

在编写处理网页文本的程序时,经常会有查找符合某些复杂规则的字符串的需求,而正则表达式正好能满足这一点。正则表达式(Regular Expression)简称Regex或RE,又称为正则表示法或常规表示法,常常用于检索,替换符合某个模式的文本。

1. Python正则表达式模块

使用re的步骤为:先将正则表达式的字符串形式编译为Pattern实例;然后使用Pattern实例处理文本并获得匹配结果(一个Match实例);最后使用Match实例获得信息,进行其他的操作。re模块中常用的方法及其说明如下。

方法说明
compile将正则表达式的字符串转化为Pattern匹配对象
match将输入的字符串从头开始对输入的正则表达式进行匹配,一直向后直至遇到无法匹配的字符或到达字符串末尾,将立即返回None,否则获取匹配结果
search将输入的字符串整个扫描,对输入的正则表达式进行匹配,获取匹配结果,否则输出None
split按照能够匹配的字符串作为分隔符,将字符串分割后返回一个列表
findall搜索整个字符串,返回一个列表包含全部能匹配的子串
finditer与findall方法作用类似,以迭代器的形式返回结果
sub使用指定内容替换字符串中匹配的每一个子串内容

compile方法

re模块中使用compile方法将正则表达式的字符串转化为Pattern匹配对象,compile方法的语法格式如下。

re.compile(string[,flag])

compile方法常用的参数及其说明如下。

参数说明
string接收string。表示需要转换的正则表达式的字符串。无默认值
flag接收string。表示匹配模式,取值为运算符“|”时表示同时生效,如re.I|re.M。默认为None

flag参数的可选值如下。  

可选值说明
re.I忽略大小写
re.M多行模式,改变“^”和“$”的行为
re.S“.”任意匹配模式,改变“.”的行为
re.L使预定字符类\w\W\b\B\s\S取决与当前区域设定
re.U使预定字符类\w\W\b\B\s\S\d\D取决于unicode定义的字符属性
re.X详细模式,该模式下正则表达式可为多行,忽略空白字符并可加入注释

search方法

earch方法将输入的字符串整个扫描,对输入的正则表达式进行匹配,若无可匹配字符,将立即返回None ,否则获取匹配结果,search方法的语法格式如下。

re.search(pattern,string[,**flags])

search方法常用的参数及其说明如下。

参数说明
pattern接收Pattern实例。表示转换后的正则表达式。无默认值
string接收string。表示输入的需要匹配的字符串。无默认值
flag接收string。表示匹配模式,取值为运算符“|”时表示同时生效,如re.I|re.M。默认为None
import re
# 搜索出字符串中所有的数字
pat = re.compile(r'\d+')   # 转换用于匹配数字的正则表达式
print("成功匹配:", re.search(pat,'abc45'))   # 成功匹配到45

# 从abc34def字符串中找出所有数字
print("匹配结果为:",re.search(pat,"acb34def"))

#从abc34def56字符串中找出所有数字
for num in re.findall(pat,"abc34def56"):
    print(num,end=" ")

import re
    string="狗的英文:dog。猫的英文:cat。"
    # 匹配出所有的中文
    reg=re.compile(r"[\u4e00-\u9fa5]+")
    print(re.findall(reg,string))

findall方法

findall方法搜索整个string,返回一个列表包含全部能匹配的子串,其语法格式如下。

re.findall(pattern,string**[,flags])

findall方法常用的参数及其说明如下

参数说明
pattern接收Pattern实例。表示转换后的正则表达式。无默认值
string接收string。表示输入的需要匹配的字符串。无默认值
flag接收string。表示匹配模式,取值为运算符“|”时表示同时生效,如re.I|re.M。默认为None
import re
# 找出字符串中所有的数字,返回为列表
pat = re.compile(r'\d+')   # 转换用于匹配数字的正则表达式
print("成功找出:", re.findall(pat,'ab2c3ed'))   # 将找出其中的2、3
for i in re.findall(pat,'ab2c3ed'):
    print(i)

2. 获取网页中的标题内容

分别使用re库中search方法和findall方法查找使用requests库获取的网页内容中的title内容。

使用正则表达式无法很好的定位特定节点并获取其中的链接和文本内容,而使用Xpath和Beautiful Soup能较为便利的实现这个功能。

# 使用Reuqests爬取网页源代码,
# 使用正则表达式获得网页的标题
import requests
import re
url="http://www.tipdm.com/tipdm/index.html"
reg=requests.get(url)
#获得的网页源代码
text=reg.text
print(text)
#使用正则表达式匹配网页源代码中的<title></title>
#使用该正则表达式抓取整个网页源代码中
#<title>泰迪科技-专注于大数据技术研发及知识传播</title>
title_patten=r"(?<=<title>).*?(?=</title>)"
#表示从抓取出来的标题中去除<title>和</title>,还有中间文字中的空格
pat=re.compile(title_patten,re.M|re.S)
result=re.search(title_patten,text)
print("获得的标题:",result.group())

# 第二种方式
print("使用findall方法获得网页标题:",
      re.findall(r"<title>(.*?)</title>",text))
#<a>CBDA国际培训中心</a>
print(re.findall(r"<a>(.*?)</a>","<a>CBDA国际培训中心</a>"))

for a in re.findall(r"<li>(.*?)</li>",text):
    #需要字符串切割,去除属性
    print(a)

运行结果:

标题内容: 泰迪科技-专注于大数据技术研发及知识传播 标题内容: ['泰迪科技-专注于大数据技术研发及知识传播']

使用正则表达式无法很好地定位特定节点并获取其中的链接和文本内容,而使用Xpath和Beautiful Soup能较为便利的实现这个功能。

通过pymysql连接数据库

# 使用pymysql模块操作mysql数据库
import pymysql
# 连接数据库之前,需要提供四个参数
# 1.连接数据库的ip地址或者主机名
# 2.mysql数据库的端口号
# 3.登录数据库的用户名
# 4.登录数据库的密码
# 第一种方式设置参数连接数据库
import pymysql
# host:主机名
# port:端口号
# user:用户名
# passwd:密码
# db:数据库名称
# charset:数据库的编码格式
# connect_timeout:连接超时时间,如果没有连上数据库,根据设定的时间范围内不再连接
con=pymysql.connect(host="127.0.0.1",port=3306,
                    user="root",passwd="root",
                    db="test",charset="utf8",
                    connect_timeout=1000,use_unicode=True)
# 第二种方式不需要参数名称连接数据库
# 第一个参数表示ip地址
# 第二个参数表示用户名
# 第三个参数表示密码
# 第四个参数表示连接的数据库名称
# con=pymysql.connect("127.0.0.1","root","root","test")

# 使用sql语句创建数据库表 id  name  text
sql="""create table if not exists tb_text(
        id int(10) primary key auto_increment,
        name varchar(20) not null,
        text varchar(200) not null
) """

# 连接上数据库后,需要创建游标
cursor=con.cursor()
# 执行创建表的sql语句
cursor.execute(sql)
# 打开创建的表进行展示
cursor.execute("show tables")

# 使用添加的sql语句往数据库中添加数据
sql=""" insert into tb_text(name,text) values(%s,%s)
        
 """
cursor.execute(sql,("章紫萱","江西机电职业学院计应专业2班班长"))
# 对表的修改包含:添加数据,修改数据,删除数据
# 一定需要事务提交
con.commit()


import pymysql
#连接数据库
con=pymysql.connect(host="127.0.0.1",port=3306,user="root",
                    passwd="root",db="test",charset="utf8",connect_timeout=1000)
#获得操作该数据库的游标
cursor=con.cursor()

#查询id在10到20范围内信息
def one():
    sql="""select * from tb_text where id > %s and id< %s """
    cursor.execute(sql,(10,20))
    data=cursor.fetchall()
    print(data)

#查询id大于等于10,id小于等于20的信息,并按id降序排列
def two():
    sql="""select * from tb_text where id between %s and %s order by id desc """
    cursor.execute(sql, (10, 20))
    data = cursor.fetchall()
    print(data)

#修改语句,将id为1的信息的name改为111,text改为222
def three():
    sql="""update tb_text set name=%s,text=%s where id=%s """
    cursor.execute(sql,(111,222,1))
    con.commit()
    #将修改后的信息查询出来
    sql="""select * from tb_text where id=%s"""
    cursor.execute(sql,(1,))
    data=cursor.fetchall()
    print(data)

#删除语句,将id为40-80的数据进行删除
def four():
    sql="""delete from tb_text where id between %s and %s"""
    cursor.execute(sql,(40,80))
    con.commit()

if __name__ == "__main__":
    four()




 

使用Xpath解析网页

XML路径语言(XML Path Language,XPath)是一门在XML文档中查找信息的语言。XPath最初被设计用来搜寻XML文档,但是同样适用于HTML文档的搜索。XPath的选择功能十分强大,它提供了非常简洁明了的路径选择表达式,还提供了超过100个内建函数,用于字符串,数值,时间的匹配,以及节点,序列的处理等等,几乎所有定位的节点都可以用XPath来选择。要使用该库也是先要通过pip进行下载安装后才能使用。这里下载的库为lxml库,而并不是XPath。

1. 基本语法

使用XPath需要从lxml库中导入etree模块,还需要使用HTML类对需要匹配的HTML对象进行初始化。HTML类的基本语法格式如下:

lxml.etree.HTML(text,parser=None,*,base_url=None)

HTML类的常用参数及其说明如下:

参数名称说明
text接收str。表示需要转换为HTML的字符串。无默认值
parser接收str。表示选择的HTML解析器。无默认值
base_url接收str。表示文档的原始URL,用于查找外部实体的相对路径。默认为None
# 导入etree模块
from lxml import etree
# 调用requests库获取的网页
import requests
url = 'http://www.tipdm.com/tipdm/index.html'
ua = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) Chrome/65.0.3325.181'}
rqg = requests.get(url,headers = ua)
# 初始化HTML
html = rqg.content
html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
# 输出修正后的HTML(如有必要)
result = etree.tostring(html,encoding='utf-8',pretty_print=True, method="html")
print("修正后的HTML:", result)

输出的数据是字节,如果需要获得字符串,则需要调用decode函数转换编码格式。

如果需要加载本地的html文件的话,XPath可能做到。

# 导入etree模块
from lxml import etree
# 从本地文件导入,test.html为保存的使用requests库获取的网页
html_local = etree.parse('./test.html', etree.HTMLParser(encoding='utf-8'))
result = etree.tostring(html_local)
print("本地文件导入的HTML:", result)

Xpath使用类似正则的表达式来匹配HTML文件中的内容,常用匹配表达式如下。

表达式说明
nodename选取nodename节点的所有子节点
/从当前节点选取直接子节点
//从当前节点选取子孙节点
.选取当前节点
..选取当前节点的父节点
@选取属性

子节点表示当前节点的下一层节点,子孙节点表示当前节点的所有下层节点,父节点表示当前节点的上一层节点。

# 导入etree模块
from lxml import etree
# 调用requests库获取的网页
import requests
url = 'http://www.tipdm.com/tipdm/index.html'
ua = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) Chrome/65.0.3325.181'}
rqg = requests.get(url,headers = ua)
# 初始化HTML
html = rqg.content
html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
# 通过名称定位head节点
result = html.xpath('head')
print("名称定位结果:", result)
# 按节点层级定位title节点
result1 = html.xpath('/html/head/title')
print("节点层级定位结果:", result1)
# 通过名称定位title节点
result2 = html.xpath('title')
print("名称定位title节点结果:", result2)
# 另一种方式定位title节点,当前节点为html节点,title是html节点的孙节点,因此需要加双斜杠
result3 = html.xpath('//title')
print("搜索定位title节点结果:", result3)

输出结果:

名称定位结果: [<Element head at 0x365c4c8>]

节点层级定位结果: [<Element title at 0x365c508>]

名称定位title节点结果: [] 搜索定位title节点结果: [<Element title at 0x365c508>]

以上代码中,直接使用名称无法定位子孙节点的title节点,因为名称只能定位子节点的head节点或body节点。

2. 谓语

Xpath中的谓语用来查找某个特定的节点或包含某个指定的值的节点,谓语被嵌在路径后的方括号中,如下。

表达式说明
/html/body/div[1]选取属于body子节点下的第一个div节点
/html/body/div[last()]选取属于body子节点下的最后一个div节点
/html/body/div[last()-1]选取属于body子节点下的倒数第二个div节点
/html/body/div[positon()<3]选取属于body子节点下的下前两个div节点
/html/body/div[@id]选取属于body子节点下的带有id属性的div节点
/html/body/div[@id=”content”]选取属于body子节点下的id属性值为content的div节点
/html /body/div[xx>10.00]选取属于body子节点下的xx元素值大于10的节点
# 定位header节点
result1 = html.xpath('//header[@class]')
print("class属性定位结果:", result1 )
# 定位ul节点
result2 = html.xpath('//ul[@id="menu"]')
print("id属性定位结果:", result2)

输出结果:

class属性定位结果: [<Element header at 0x365dbc8>]

id属性定位结果: [<Element ul at 0x365db48>]

3. 功能函数

Xpath中还提供功能函数进行模糊搜索,有时对象仅掌握了其部分特征,当需要模糊搜索该类对象时,可使用功能函数来实现,具体函数如下。

功能函数示例说明
starts-with//div[starts-with(@id,”co”)]选取id值以co开头的div节点
contains//div[contains(@id,”co”)]选取id值包含co的div节点
and//div[contains(@id,”co”)andcontains(@id,”en”)]选取id值包含co和en的div节点
text()//li[contains(text(),”first”)]选取节点文本包含first的div节点
# 获取title节点的文本内容
title = html.xpath('//title/text()')
print("title节点的文本内容:", title)

4. 提取header节点下全部标题文本及对应链接

使用text方法可以提取某个单独子节点下的文本,若想提取出定位到的子节点及其子孙节点下的全部文本,则需要使用string方法实现。

使用HTML类将其初始化通过requests库获取的网页,之后使用谓语定位id值以me开头的ul节点,并使用text方法获取其所有子孙节点a内的文本内容,使用@选取href属性从而实现提取所有子孙节点a内的链接,最后使用string方法直接获取ul节点及其子孙节点中的所有文本内容。

# 定位id值以me开头的ul节点并提取其所有子孙节点a内的文本内容
content=html.xpath('//ul[starts-with(@id,"me")]/li//a/text()')
for i in content:
    print(i )
# 结果:
	首页
	产品中心
	学科建设
	培训认证
	企业应用
	校企合作
	新闻中心
	关于我们
# 提取对应链接
url_list = html.xpath('//ul[starts-with(@id,"me")]/li//a/@href')
for i in url_list:
    print(i)
# 结果:
/
/tipdm/cpzx/
http://www.tipdm.com:80/xkjs/index.jhtml
http://www.tipdm.com:80/pxrz/index.jhtml
http://www.tipdm.com:80/qyyy/index.jhtml
http://www.tipdm.com:80/xqhz/index.jhtml
http://www.tipdm.com:80/xwzx/index.jhtml
/tipdm/gywm/
# 定位id值以me开头的ul节点
target=html.xpath('//ul[starts-with(@id,"me")]')
# 提取该节点下的全部文本内容
target_text = target[0].xpath('string(.)').strip()    # strip方法用于去除多余的空格
print("节点下的全部文本内容:", target_text)
# 结果:
	首页
	产品中心
	学科建设
	培训认证
	企业应用
	校企合作
	新闻中心
	关于我们

对于XPath库的使用需要结合Requests库的地址访问进行熟练掌握解析网页的数据。多多练习!!!

# XPath项目库用于解析网页源代码,在爬虫技术中并不能单独使用
# 需要进行结合各种爬取网页源代码的技术进行综合使用
# urllib,urllib3,requests用于爬取指定的网页源代码
import requests
from lxml import etree
url="http://www.tipdm.com/tipdm/index.html"
rqg=requests.get(url)
print(rqg.status_code)
print(rqg.encoding)
#rqg.encoding="gbk"
print(rqg.text)

# 在使用XPath解析网页源代码之前,需要学习使用XPath转换编码格式
# 语法格式:
# lxml.etree.html(text,parser=lxml.etree.HTMLParser(encoding="UTF-8"))
html=etree.HTML(rqg.text,parser=etree.HTMLParser(encoding="UTF-8"))
# tostring:表示将源代码按字节输出
#html=etree.tostring(html)

#从整个网页源代码中解析出head标签
# 使用的 nodename直接标明标签名称
head=html.xpath("head")
print("获得的head标签对象:",head)
# 使用 /当前标签名称 解析title标签对象
title=html.xpath("/html/head/title")
print("获得title标签对象:",title)
# 直接指定内部,不能直接跨越多级标签路径获取孙标签的对象
title1=html.xpath("title")
# 获取不到
print("获得title标签对象:",title1)
# 使用 // 获得三级标签
title2=html.xpath("//title")
print("获得title标签对象:",title2)

# 从网页中找到body中的header标签对象,通过class选择器查找
header=html.xpath("//header[@class]")
print("获得body中的header标签对象:",header)

#查找ul标签
ul=html.xpath("//ul[@id='menu']")
print("获得ul标签对象:",ul)

#获得title标签中的文字信息
t=html.xpath("//title/text()")
print("获得title标签的文本信息:",t)

# 获取导航栏上的所有超链接
menu=html.xpath("//ul[@id='menu']/li/a/text()")
for m in menu:
    print("导航栏:",m)

# 获取导航栏上的所有超链接
menu=html.xpath("//ul[@id='menu']/li/a/@href")
for m in menu:
    print("超链接地址:",m)

 




import requests

# 指定网址requests进行爬取网页源代码
def one():
    url="http://www.tipdm.com/tipdm/index.html"
    reg=requests.get(url)
    text=reg.text
    two(text)

# 将用XPath解析网页源代码,获取一部分数据
from lxml import etree
def two(text):
    # 爬取导航栏对应的超链接上的地址
    html=etree.HTML(text,etree.HTMLParser(encoding="UTF-8"))
    urls=html.xpath("//ul[@id='menu']/li/a/@href")
    three(urls)

# 使用pymysql将获取的一部分数据存储至数据表中
import pymysql
def three(urls):
    con=pymysql.connect(host="127.0.0.1",port=3306,
                        user="root",passwd="root",
                        db="test",charset="utf8",connect_timeout=1000)
    cursor=con.cursor()
    sql="""create table if not exists tb_url(
        id integer primary key auto_increment,
        url varchar(1000) not null
        )
    """
    cursor.execute(sql)

    #将爬取的数据存储至mysql数据库
    for u in urls:
        sql="""insert into tb_url(url) values(%s)"""
        cursor.execute(sql,(u,))
        con.commit()

#程序入口
if __name__ =="__main__":
    one()


使用Beautiful Soup解析网页

Beautiful Soup是一个可以从HTML或XML文件中提取数据的Python库。目前Beautiful Soup 3已经停止开发,大部分的爬虫选择使用Beautiful Soup 4开发。该库的使用也是需要通过pip进行下载和安装的bs4.

Beautiful Soup不仅支持Python标准库中的HTML解析器,还支持一些第三方的解析器,具体语法如下。  

解析器语法格式优点缺点
Python标准库BeautifulSoup(markup, "html.parser")1.Python的内置标准库 2.执行速度适中 3.文档容错能力强Python 2.7.3或3.2.2前的版本中文档容错能力差
lxml HTML解析器BeautifulSoup(markup, "lxml")1.速度快 2.文档容错能力强需要安装C语言库
lxml XML解析器BeautifulSoup(markup, ["lxml-xml"]) BeautifulSoup(markup, "xml")1.速度快 2.唯一支持XML的解析器需要安装C语言库
html5libBeautifulSoup(markup, "html5lib")1.最好的容错性 2.以浏览器的方式解析文档 3.生成HTML5格式的文档速度慢 不依赖外部扩展

1. 创建BeautifulSoup对象

要使用Beautiful Soup库解析网页首先需要创建BeautifulSoup对象,将字符串或HTML文件传入Beautiful Soup库的构造方法可以创建一个BeautifulSoup对象,使用格式如下。

BeautifulSoup("<html>data</html>") #通过字符串创建

BeautifulSoup(open("index.html")) #通过HTML文件创建

生成的BeautifulSoup对象可通过prettify方法进行格式化输出,其语法格式如下。

BeautifulSoup.prettify**(self, encoding=None, formatter='minimal')

prettify方法常用的参数及其说明如下。

参数说明
encoding接收string。表示格式化时使用的编码。默认为None
formatter接收string。表示格式化的模式。默认为minimal,表示按最简化的格式化将字符串处理成有效的HTML∕XML
# BeautifulSoup的使用
from bs4 import BeautifulSoup
import requests
url = 'http://www.tipdm.com/tipdm/index.html'
ua = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) Chrome/65.0.3325.181'}
# 发出访问请求并携带请求头参数信息
rqg=requests.get(url,headers=ua)
# 将获取的字节源代码转换成UTF-8编码格式
html=rqg.content.decode("UTF-8")
# 将源代码使用XPath作为解析器解析为BeautifulSoup库的对象
soup=BeautifulSoup(html,"lxml")
# 并将内容进行格式化后输出
print("输出格式化的BeautifulSoup对象:",soup.prettify())

大家自行编写运行查看效果,输出的是该页面的源码。

2. 对象类型

Tag对象类型

•Tag对象为HTML文档中的标签,形如“<title>The Dormouse's story</title>”或“<p class="title">The Dormouse's story</p>”等HTML标签再加上其中包含的内容便是Beautiful Soup中的Tag对象。

•通过Tag的名称属性可以很方便的在文档树中获取需要的Tag对象,通过该方法只能获取文档树中第一个同名的Tag对象,而通过多次调用可获取某个Tag对象下的分支Tag对象。通过find_all方法可以获取文档树中的全部同名Tag对象。

print("获取head标签:", soup.head)    # 获取head标签
soup.title  # 获取title标签
print("获取第一个a标签:", soup.body.a)   # 获取body标签中的第一个a标签
print("所有名称为a的标签的个数:" , len(soup.find_all('a')))    # 获取所有名称为a的标签的个数

•Tag有两个非常重要的属性:name和attributes。name属性可通过name方法来获取和修改,修改过后的name属性将会应用至BeautifulSoup对象生成的HTML文档。

print("soup的name:" , soup.name)    # 获取soup的name
print("a标签的name:" , soup.a.name)     # 获取a标签的name
tag = soup.a
print("tag的name:" , tag.name)       # 获取tag的name
print ("tag的内容:" , tag)
tag.name = 'b'    # 修改tag的name
print ("修改name后tag的内容:" , tag)            # 查看修改name后的HTML
print("Tag对象的全部属性:" , tag.attrs)    # 获取Tag对象的全部属性
print("class属性的值:" , tag['class'])     # 获取class属性的值
tag['class'] = 'Logo'  # 修改class属性的值
print("修改后Tag对象的属性:" , tag.attrs)
tag['id'] = 'logo'  # 新增属性id,赋值为logo
del tag['class']      # 删除class属性
print ("修改后tag的内容:" , tag)

NavigableString对象类型

NavigableString对象为包含在Tag中的文本字符串内容,如“<title>The Dormouse‘s story</title>”中的“The Dormouse’s story”,使用string的方法获取,NavigableString对象无法被编辑,但可以使用replace_with的方法进行替换。

tag = soup.title
print ("Tag对象中包含的字符串:" , tag.string)    # 获取Tag对象中包含的字符串
print ("tag.string的类型:" , type(tag.string))     # 查看类型
tag.string.replace_with("泰迪科技")   # 替换字符串内容
print ("替换后的内容:" , tag.string)

BeautifulSoup对象类型

BeautifulSoup对象表示的是一个文档的全部内容。大部分时候,可以把它当作Tag对象。 BeautifulSoup对象并不是真正的HTML或XML的tag,所以并没有tag的name和attribute属性,但其包含了一个值为“[document]”的特殊属性name。

print ("soup的类型:" , type(soup))     # 查看类型
print ("BeautifulSoup对象的特殊属性name:" , soup.name)    # BeautifulSoup对象的特殊属性name
print ("soup.name的类型:" , type(soup.name))
print ("BeautifulSoup对象的attribute属性:" , soup.attrs)     # BeautifulSoup对象的attribute属性为空

Comment对象类型

Tag、NavigableString、BeautifulSoup几乎覆盖了html和xml中的所有内容,但是还有一些特殊对象,文档的注释部分是最容易与Tag中的文本字符串混淆的部分。Beautiful Soup库中将文档的注释部分识别为Comment类型,Comment对象是一个特殊类型的NavigableString对象,但是当其出现在HTML文档中时,Comment对象会使用特殊的格式输出,需调用prettify方法。

markup = "<c><!--This is a markup--></c>"
soup_comment = BeautifulSoup(markup, "lxml")
comment = soup_comment.c.string    # comment对象也由string方法获取
print ("注释的内容:" , comment)               # 直接输出时与一般NavigableString对象一致
print ("注释的类型:" , type(comment))          # 查看类型

3. 搜索特定节点并获取其中的链接及文本

Beautiful Soup定义了很多搜索方法,其中常用的有find方法和find_all方法,两者的参数一致,区别为find_all方法的返回结果是值包含一个元素的列表,而find直接返回的是结果。find_all方法用于搜索文档树中的Tag非常方便,其语法格式如下。

BeautifulSoup.find_all(name,attrs,recursive,string,**kwargs**)

find_all方法的常用参数及其说明如下。

参数说明
name接收string。表示查找所有名字为name的tag,字符串对象会被自动忽略掉,搜索name参数的值可以使用任一类型的过滤器:字符串、正则表达式、列表、方法或True。无默认值
attrs接收string。表示查找符合CSS类名的tag,使用class做参数会导致语法错误,从Beautiful Soup的4.1.1版本开始,可以通过class_参数搜索有指定CSS类名的tag。无默认值
recursive接收Built-in。表示是否检索当前tag的所有子孙节点。默认为True,若只想搜索tag的直接子节点,可将该参数设为False
string接收string。表示搜索文档中匹配传入的字符串的内容,与name参数的可选值一样,string参数也接收多种过滤器。无默认值
**kwargs若一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索

find_all方法可通过多种参数遍历搜索文档树中符合条件的所有子节点。

•可通过name参数搜索同名的全部子节点,并接收多种过滤器。

•按照CSS类名可模糊匹配或完全匹配。完全匹配class的值时,如果CSS类名的顺序与实际不符,将搜索不到结果。

•若tag的class属性是多值属性,可以分别搜索tag中的每个CSS类名。

•通过字符串内容进行搜索符合条件的全部子节点,可通过过滤器操作。

•通过传入关键字参数,搜索匹配关键字的子节点。

# 通过name参数搜索名为title的全部子节点
print ("名为title的全部子节点:" , soup.find_all("title "))
print ("title子节点的文本内容:" , soup.title.string)
print ("使用get_text()获取的文本内容:" , soup.title.get_text())
target = soup.find_all("ul", class_="menu")   # 按照CSS类名完全匹配
print("CSS类名匹配获取的节点:" , target)
target = soup.find_all(id='menu')            # 传入关键字id,按符合条件的搜索
print("关键字id匹配的节点:" , target)
target = soup.ul.find_all('a')
print("所有名称为a的节点:" , target)
# 创建两个空列表用于存放链接及文本
urls = []
text = []
# 分别提取链接和文本
for tag in target:
    urls.append(tag.get('href'))
    text.append(tag.get_text())
for url in urls:
    print(url)
for i in text:
    print(i)

3.3 数据存储

爬虫通过解析网页获取页面中的数据后,还需要将获得的数据存储下来以供后续分析。使用JSON模块将XPath获取的文本内容存储为JSON文件,使用PyMySQL库将Beautiful Soup库获取的标题存入MySQL数据库。

1. 将数据存储为JSON文件

将数据存储为JSON文件的过程为一个编码过程,编码过程常用dump函数和dumps函数。两者的区别在于,dump函数将Python对象转换为JSON对象,并通过fp文件流将JSON对象写入文件内,而dumps函数则生成一个字符串。dump函数和dumps函数的语法格式如下。

json.dump(obj,fp,skipkeys=False,ensure_ascii=True,check_circular=True,allow_nan=True,cls=None,indent=None,separators=None,encoding**='utf-8', default=None, sort_keys=False, **kw**)

json.dumps(obj,skipkeys**=False, ensure_ascii**=True, check_circular=True,allow_nan**=True,

cls=None,indent=None,separators=None,encoding**='utf-8', default=None, sort_keys=False, **kw**)

dump函数和dumps函数的常用参数及其说明如下。

参数说明
skipkeys接收Built-in。表示是否跳过非Python基本类型的key,若dict的keys内的数据为非Python基本类型,即不是str、unicode、int、long、float、bool、None等类型,设置该参数为False时,会报TypeError错误。默认值为False,设置为True时,跳过此类key
ensure_ascii接收Built-in。表示显示格式,若dict内含有非ASCII的字符,则会以类似“\uXXX”的格式显示。默认值为True,设置为False后,将会正常显示
indent接收int。表示显示的行数,若为0或为None,则在一行内显示数据,否则将会换行且按照indent的数量显示前面的空白,将JSON内容格式化显示。默认为None
separators接收string。表示分隔符,实际上为(item_separator,dict_separator)的一个元组,默认为(',',':'),表示dictionary内的keys之间用“,”隔开,而key和value之间用“:”隔开。默认为None
encoding接收string。表示设置的JSON数据的编码形式,处理中文时需要注意此参数的值。默认为UTF-8
sort_keys接收Built-in。表示是否根据keys的值进行排序。默认为False,为True时数据将根据keys的值进行排序
import json
# 使用requests和Xpath获取数据
from lxml import etree
import requests
import chardet
url = 'http://www.tipdm.com/tipdm/index.html'
ua = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) Chrome/65.0.3325.181'}
rqg = requests.get(url,headers = ua)
rqg.encoding = chardet.detect(rqg.content)['encoding']
html = rqg.content.decode('utf-8')
html = etree.HTML(html,parser=etree.HTMLParser(encoding='utf-8'))
content=html.xpath('//ul[starts-with(@id,"me")]/li//a/text()')
print("标题菜单的文本:", content)
# 使用dump方法写入文件,该执行的方法取别名
# with open('output.json','w') as fp:
#     json.dump(content,fp)
f=open("output.json","w")
json.dump(content,f)
# 通过指定的网站地址requests爬取网页源代码
# Xpath解析网页源代码获得我们想要的数据
# Json将解析的数据存储在本地文件中
import requests
from lxml import etree
import json
url="http://www.tipdm.com/tipdm/index.html"
# 获取网页源代码
reg=requests.get(url)
# 获得xpath解析的对象,对网页源代码做编码格式处理
html=etree.HTML(reg.text,parser=etree.HTMLParser(encoding="UTF-8"))
# 从网页源代码中获得“深圳市福田区信访局”
content=html.xpath("//section[@id='hzhb']//ul/li/a/@title")
print("解析的内容为:",content[0])
# 将解析的数据使用json格式存储在本地文件中
# 定义文件名文件的权限
f=open("output.json","w")
# 将数据按json格式写入该文件中
json.dump(content[0],f)

 

2. 将数据存储入MySQL数据库

连接方法

pymysql模块使用connect方法连接数据库,connect方法的语法格式如下。

pymysql.connect(host,port,user,passwd,db,charset,connect_timeout,use_unicode**)

connect方法有很多参数可供使用,其常用的参数及其说明如下。

参数说明
host接收string。表示数据库地址,本机地址通常为127.0.0.1。默认为None
port接收string。表示数据库端口,通常为3306。默认为0
user接收string。数据库用户名,管理员用户为root。默认为None
passwd接收string。表示数据库密码。默认为None
db接收string。表示数据库库名。无默认值
charset接收string。表示插入数据库时的编码。默认为None
connect_timeout接收int。表示连接超时时间,以秒为单位。默认为10
use_unicode接收string。表示结果以unicode字符串返回。默认为None
import pymysql
# 使用参数名创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='admin', db='test', charset='utf8',
 connect_timeout=1000)
# 不使用参数名创建连接
conn = pymysql.connect('127.0.0.1', 'root', 'admin', 'test')

数据库操作函数

pymysql中可以使用函数返回的连接对象connect进行操作,常用的函数如下。

函数说明
commit提交事务。对支持事务的数据库或表,若提交修改操作后,不使用该方法,则不会写入数据库中
rollback事务回滚。在没有commit前提下,执行此方法时,回滚当前事务
cursor创建一个游标对象。所有的sql语句的执行都需要在游标对象下进行

在python操作数据库的过程中,通常主要是使用connect.cursor方法获取游标,或使用cursor.execute方法对数据库进行操作,如创建数据库以及数据表等操作,通常使用更多的为增、删、改、查等基本操作。游标对象也提供了很多种函数,常用函数如下。

函数说明语法格式
close关闭游标close()
execute执行sql语句execute(sql)
excutemany执行多条sql语句excutemany(sql)
fetchone获取执行结果中的第一条记录fetchone()
fetchmany获取执行结果中的n条记录fetchmany(n)
fetchall获取执行结果的全部记录fetchall()
scroll用于游标滚动scroll()
import pymysql
# 使用参数名创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='admin', db='test', charset='utf8', connect_timeout=1000)
# 创建游标
cursor=conn.cursor()
# 创建表
sql="""create table if not exists class (id int(10) primary key auto_increment,name varchar(20) not null,text varchar(20) not null)"""
cursor.execute(sql)            # 执行创建表的sql语句
cursor.execute("show tables")    # 查看创建的表
# 数据准备
import requests
import chardet
from bs4 import BeautifulSoup
url = 'http://www.tipdm.com/tipdm/index.html'
ua = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) Chrome/65.0.3325.181'}
rqg = requests.get(url,headers = ua)
rqg.encoding = chardet.detect(rqg.content)['encoding']
html = rqg.content.decode('utf-8')
soup = BeautifulSoup(html, "lxml")
target = soup.title.string
print("标题的内容:", target)
# 插入数据
title = "tipdm"
sql = "insert into class (name,text)values(%s,%s)"
cursor.execute(sql,(title,target))          # 执行插入语句
conn.commit()           # 提交事务
# 查询数据
data=cursor.execute("select * from class")
# 使用fetchall方法获取操作结果
data=cursor.fetchmany()
print("查询获取的结果:", data)
conn.close()

小结

(1) 分别通过urllib3库和Requests库建立HTTP请求,从而与网站建立链接并获取网页内容。相比urllib3库,Requests库使用起来更为简洁直观。

(2) 使用Chrome开发者工具可方便地直接查看页面元素,页面源码及资源加载过程。

(3) 通过正则表达式可按照模式对网页内容进行匹配,查找符合条件的网页内容,缺点为不易上手且容易产生分歧。

(4) 通过lxml库中的etree模块实现使用Xpath解析网页。通过表达式及谓语可查找特定节点,也可提供功能函数

进行模糊查询和内容获取

(5) Beautiful Soup 库可从HTML或XML文件中提取数据,并可提供函数处理导航,搜索,修改分析树的功能。

(6) JSON模块可提供Python对象与JSON对象的互相转换功能,并可提供存储数据为JSON文件的功能。

(7) PyMySQL库可提供操作MySQL的功能,内含数据库连接方法及多种操作函数。

Python爬虫需要登录的网站(附爬虫视频教程)_python 爬虫如何需要登录
2401_84424379的博客
04-17 560
使用cookie登陆,服务器会认为你是一个已登陆的用户,所以就会返回给你一个已登陆的内容。因此,需要验证码的情况可以使用带验证码登陆的cookie解决。对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!
python爬虫+简单信息内容+网页资料
最新发布
01-30
再看看第2页,会发现url最后面以‘&s=44’结束,第三页则是‘&s=88’......依次类推,每一页显示44个商品。 内容存入指定目录txt文件中。 爬虫是什么 爬虫简单的来说就是用程序获网络上数据这个过程的一种名称。 ...
通过爬虫500px的编辑推荐的照片进行数据分析
01-12
通过爬虫500px的编辑推荐的照片进行数据分析
3000字 “婴儿级” 爬虫图文教学 | 手把手教你用Python “实习网”!
pdcfighting的博客
05-26 345
点击上方“Python爬虫与数据挖掘”,进行关注回复“书籍”即可获赠Python从入门到进阶共10本电子书今日鸡汤潮平两岸阔,风正一帆悬。1. 为"你"而写 这篇文章,是专...
Python爬虫 | 碰到动态页面如何?处理思路分享
WANGJUNAIJIAO的博客
05-16 2674
说到网页,我们一般的操作是先查看源代码或者审查元素,找到信息所在节点,然后用 beautifulsoup/xpth/re 来获数据,这是我们对付静态网页的常用手段。先来梳理一下的流程:1、先引入需要的包,可以边写边引入,用到哪个包就引入哪个包 from xxx import xxx2、按F12,选择network选项,找到type为document或js或XHR的页面,把header内容出来。3、把url也出来,等待解析 url = xxx。
python使用chardet判断字符串编码,超简单的代码
weixin_30832405的博客
07-26 435
下面代码段是关于python使用chardet判断字符串编码,超简单的代码,应该是对码农有较大用。 import chardetf = open('file','r')fencoding=chardet.detect(f.read())print fencoding ...
爬虫chrome分析post和json-1-寻找post地址
weixin_44464367的博客
08-13 1043
寻找url地址的两种方法 1、在form表单中寻找action对应的url地址 post数据是input标签中name的值最为键,真正的用户名密码作为值的字典; post的url地址就是action对应的url地址。 以人人网为例,未登录状态下: Elements里的form表单,form里有一个action,即url地址,可通过Ctrl F搜索form 点击需要输入用户名密码的左侧窗口,E...
基于python的网络爬虫天气数据及可视化分析python大作业,程设计报告
06-13
基于python的网络爬虫天气数据及可视化分析 python程序设计报告 源代码+csv文件+设计报告 python期末简单大作业(自己写的,重复率低) 利用python了网站上的城市天气,并用利用可视化展示,有参考文献有目录
python爬虫大作业报告+代码
12-30
所学Python技术设计并实现一个功能完整的系统,并撰写总结报告。 要求: (1)实现时需要至少使用图形界面、多线程、文件操作、数据库编程、网页爬虫、统计 分析并绘图(或数据挖掘)六项技术,缺一不可。少一项则直接影响是否及格。 (2)系统要具有一定复杂度。应用系统的业务流程不能过于简单,数据库表不能少于5张表。图片不能少于500张。采集数据不能少于1000条,统计分析的目标不能少于3个。 (3)实现时要考虑模块化,不能将所有功能均在一个程序内实现。
python网站数据(含代码和讲解)
weixin_50706330的博客
09-29 5万+
python网站数据~
Python爬虫——简单网页(实战案例)小白篇
m0_74942241的博客
10-27 1万+
在着手写爬虫网页之前,要先把其需要的知识线路理清楚。 首先:了解相关的Http协议知识; 其次:熟悉Urllib、Requests库; 再者:开发工具的掌握 PyCharm、Fiddler; 最后:网页案例;
作业4:网页前端基础(HTTP请求方式与过程、HTTP状态码、HTTP头部信息)及静态网页(urllib3库、requests库、Xpath解析网页、Beautiful Soup解析网页
Joker_Q的博客
05-11 1733
网页前端基础及静态网页 一、HTTP请求方式与过程 1、请求方法 在HTTP/1.1协议中共定义了8种方法(也叫“动作”)来以不同方式操作指定的资源,常用的方法有GET、HEAD、POST等。 请求方法 方法描述 GET 请求指定的页面信息,并返回实体主体。GET可能会被网络爬虫等随意访问,因此GET方法应该只用在读数据,而不应当被用于产生“副作用”的操作中,例如在W...
基于python爬虫对百度贴吧进行的设计与实现.docx
10-26
《基于python爬虫对百度贴吧进行的设计与实现.docx》万字、已降重、毕业论文、本科,目录如下,希望对你有所帮助: 第一章 前言 1.1 研究背景 1.2 研究目的 1.3 研究方法 第二章 爬虫原理与相关技术 2.1 Python...
Python使用爬虫静态网页图片的方法详解
01-21
这篇就清晰地讲解一下利用Python爬虫的理论基础。 首先说明爬虫分为三个步骤,也就需要用到三个工具。 ① 利用网页下载器将网页的源码等资源下载。 ② 利用URL管理器管理下载下来的URL ③ 利用网页解析器解析需要的...
python爬虫基础操作:MySQL数据库存储的信息
12-20
本文实例讲述了Python3爬虫学习之MySQL数据库存储的信息。分享给大家供大家参考,具体如下: 数据库存储的信息(MySQL) 到的数据为了更好地进行分析利用,而之前将得数据存放在txt文件中后期处理...
python3网络爬虫系列(三)给定URL网页(访问量、阅读量)实例
01-20
已经搭建好代理IP池之后,就可以尝试用获得的代理IP访问给定URL,页面,具体的源码和更多说明在github库Simulate-clicks-on-given-URL里,供大家学习。 代码 这段代码可以返回我们需要的用户IP PROXY_POOL_URL =...
爬虫(三)—— python 爬虫小试
qq_31329259的博客
02-17 1735
一、基本概念 网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。 二、python 爬虫函数解析 2.1 requests 请求网页 requests库的7个主要的方法 函数 requests.request() 构造一个请求,支撑一下各方法的基本方法 requests.get() 获HTML网页的主要方法,对应于HTTP的GET
python爬虫+网页点击事件+selenium模拟浏览器,选股宝内容
热门推荐
weixin_42551465的博客
06-28 7万+
(一)PYTHON的安装(已安装,可跳过此不步骤)        1、PYTHON下载                PYTHON官网:https://www.python.org/                              按照对应的系统下载,我这里是window系统,点击windows,根据自己系统操作位数下载                                  ...
Python爬虫学习记录——6.浏览器抓包及headers设置
赈川
10-25 962
文章目录爬虫的一般思路分析具体网页请求实战 爬虫的一般思路 抓网页、分析请求 解析网页、寻找数据 储存数据、多页处理 本节博客主要讲授如何通过谷歌浏览器开发者工具分析真实请求的方法。 分析具体网页请求 观察以下网址翻页后的URL http://www.zkh360.com/zkh_catalog/3.html 可以发现翻页后URL并没有发生变化,思考: 翻页后URL不变该如何寻找请求?...
python爬虫第三关:菜谱网站/豆瓣top250
08-31
你好!对于菜谱网站,你可以使用 Python 的 requests 和 BeautifulSoup 库来实现。首先,你需要发送请求获网页的 HTML 内容,然后使用 BeautifulSoup 解析该内容,提出你所需的菜谱信息。 以下是一个简单的示例代码,以美食天下网站(www.meishij.net)为例: ```python import requests from bs4 import BeautifulSoup def get_recipe(url): response = requests.get(url) soup = BeautifulSoup(response.text, 'html.parser') # 在这里根据网页结构提菜谱信息 # 例如,获菜名和食材 recipe_name = soup.find('h1', class_='recipe-title').text.strip() ingredients = soup.find('div', class_='particulars').ul.find_all('li') ingredient_list = [] for ingredient in ingredients: ingredient_list.append(ingredient.text.strip()) # 输出菜谱名称和食材列表 print("菜谱名称:", recipe_name) print("食材列表:", ingredient_list) # 菜谱详情页的URL recipe_url = 'https://www.meishij.net/1' get_recipe(recipe_url) ``` 对于豆瓣 Top250 电影榜单,同样可以使用 requests 和 BeautifulSoup 库来实现。以下是一个简单的示例代码: ```python import requests from bs4 import BeautifulSoup def get_top250(): url = 'https://movie.douban.com/top250' response = requests.get(url) soup = BeautifulSoup(response.text, 'html.parser') movie_list = soup.find('ol', class_='grid_view').find_all('li') for movie in movie_list: # 获电影排名、名称和评分 rank = movie.find('em').text title = movie.find('span', class_='title').text rating = movie.find('span', class_='rating_num').text # 输出电影信息 print("排名:", rank) print("名称:", title) print("评分:", rating) print() get_top250() ``` 以上代码只是一个简单示例,你可以根据具体的网页结构和需求进行相应的修改和扩展。希望能对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • 【软考中级】2022下半年软件设计师综合知识真题与答案 13141
  • 【Java】Tomcat服务器运行不了的各种解决办法 11417
  • 【Python】第十二课 网络爬虫 9328
  • 【鸿蒙】鸿蒙App应用-《记账软件》开发步骤 6296
  • 【Java】Eclipse安装和J2EE开发环境的配置 5658

分类专栏

  • Flask 付费 10篇
  • Spring Boot 付费 10篇
  • Jsp网络编程 付费 37篇
  • Python可视化 付费 9篇
  • HarmonyOS (ArkTS) 9篇
  • HarmonyOS(Java) 33篇
  • Python 15篇
  • web前端 24篇
  • Python爬虫 4篇
  • Django服务器开发 11篇
  • 证书 10篇
  • Java算法 7篇
  • SSM框架技术 20篇
  • Redis缓存技术 1篇
  • HarmonyOS征文大赛 1篇
  • Java 19篇
  • MySQL 8篇

最新评论

  • 【鸿蒙】鸿蒙App应用-《记账软件》登录,注册,找回密码功能

    笔触狂放: 资源下载,自己摸索一下csdn

  • 【鸿蒙】鸿蒙App应用-《记账软件》登录,注册,找回密码功能

    颖浠: 你好,可以问一下“资源文件”在哪里下载?

  • 【JavaWeb】网上蛋糕项目商城-首页

    笔触狂放: 资源里面有完整代码

  • 【JavaWeb】网上蛋糕项目商城-首页

    ℳঞ溪焕: 你这个图片在哪

  • 【JavaWeb】网上蛋糕项目商城-首页

    ℳঞ溪焕: 为什么我的图片引不进去,路径也没错

大家在看

  • Docker管理工具Portainer忘记admin登录密码
  • 华为eNSP实验:Eth-Trunk手工模式
  • 企业选择合适等保服务方案几点建议 275
  • 美团商家数据采集器 6
  • 【水印工具分享】水印添加的几个简单方法,值得一试

最新文章

  • 【HarmonyOS】综合应用-《校园通》
  • 【HarmonyOS】笔记八-图片处理
  • 基于Python的飞机大战游戏
2024
05月 13篇
04月 7篇
02月 22篇
01月 25篇
2023年36篇
2022年54篇
2021年71篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笔触狂放

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值

深圳SEO优化公司海东百度竞价多少钱昭通建站大芬阿里店铺运营价格阳泉网站排名优化石岩百度关键词包年推广哪家好郑州英文网站建设聊城网站设计多少钱永州网站改版报价鞍山seo网站推广推荐兴安盟seo网站优化报价邯郸关键词按天计费哪家好铁岭网站优化软件多少钱大芬SEO按天扣费价格三明seo排名北海网页设计楚雄网站优化按天扣费公司大运网站设计哪家好梧州网站搭建价格汉中建网站多少钱黔南企业网站制作苏州seo推荐日照网页制作报价珠海建设网站多少钱广州外贸网站制作哪家好新余模板制作报价常州seo哪家好徐州seo网站推广价格莱芜网络推广公司太原网站优化价格民治企业网站设计价格歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化