简单爬虫的示例分析
以之前写的汇率爬虫示范
该网站已经改版,此爬虫代码已无效
但是还是摆出来,给大家一个爬虫入门吧
本人新手,勿喷
import requests
from bs4 import BeautifulSoup
link = "https://www.msn.cn/zh-cn/money/currencyconverter"#MSN 财经
headers = {'User-Agent' : 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
r = requests.get(link, headers= headers)
soup = BeautifulSoup(r.text, 'html.parser')
list_soup = soup.find("div", class_= "mjrcurrncsrow mjcurrncs-data")
for money_info in soup.find_all('div',class_='mcrow'):
name = money_info.find("span",class_="cntrycol").get_text("title").strip()
exchange_rate= money_info.find("span", class_= "pricecol").get_text("aria-label").strip()
Money_data = {
'货币': name,
'汇率': exchange_rate
}
print (Money_data)
import requests#这个包是用来访问网站的
from bs4 import BeautifulSoup
link = "https://www.msn.cn/zh-cn/money/currencyconverter"#MSN 财经
headers = {'User-Agent' : 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
r = requests.get(link, headers= headers)
headers是下面那个requests.get
函数的参数,可以查阅requests包的文档查看。好吧,我帮你看看,其实这个headers是HTTP的头部信息。
访问网站时,有时必须提供你的浏览器信息(头部信息),而里面的’User-Agent’这个就是用户代理配置,作用是将你的爬虫伪装成正常访问。
而上面代码里的是火狐浏览器的用户代理配置
将爬虫伪装成正常的访问,但其实如果你访问过快且过多,很容易就被看出来了然后被封IP,一般的封IP只会持续24h不用多担心。
如果你被封了,一般就会显示403错误
如何查看用户代理?进入某个浏览器,在空白网址栏上输入 浏览器名://version,例如进入edge浏览器,输入edge://version
进入即可查看
注意 {‘User-Agent’ : ‘(这个里面)’ 的才是用户代理数据。
r = requests.get(link, headers= headers)
其实requests.get()
函数还有其他的参数,是关于计算机网络的HTTP中的知识,用于url的拼接查询。
就这两个参数应该够用
如今我们爬出来的r,其实是我们访问网站的服务器响应的内容。
你可以在以上代码后添上一句代码
print(r.text)
后面的代码全部注释掉,然后运行。输出结果是这个网站的HTML源代码。就相当于你打开浏览器网页,按F12看到的的代码。我们想要的数据全部包含在里面了。
必须加上text后缀,这样才能正确输出文本形式。
requests 是唯一的一个非转基因的 Python HTTP 库,人类可以安全享用。附上官方文档的链接Requests: 让 HTTP 服务人类 — Requests 2.18.1 文档 (python-requests.org)
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库,附上官方文档的链接 Beautiful Soup 4.2.0 文档
Beautiful Soup这个才是要学习的重点,因为我们爬到数据需要提取关键信息才有利于我们分析。
soup = BeautifulSoup(r.text, 'html.parser')
这句代码的意思是将我们爬出来的源代码放入BeautifulSoup
里进行解析。而后面的参数是我们指定的解析器html.parser
。这个解析器位于python的标准库里,不需要另外安装。当然还有其他的解析器,不过它们需要安装,关于解析器的详情可以查看BeautifulSoup
官方文档。
然后代码就解析完了。你可以在以上代码后添上一句代码
print(soup)
后面也是全部注释掉。发现与print(r.text)
相比输出的更整齐了。这是因为Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象。
简单来说,我们应该就使用Beautiful Soup中的find
函数,
list_soup = soup.find("div", class_= "mjrcurrncsrow mjcurrncs-data")
用法是将我们之前解析完的soup后加上find后缀。find
函数是按照节点去查找的。详细用法在官方文档。
前面的引号里是标签的名称。例如 <div>
或者<p>
,<span>
后面是标签的class属性,find
函数只能利用class属性查询,不能利用标签的其他属性。写法是class_= " "
注意要加符号 ‘ _ ’
这句代码执行完就将这个<div class= "mjrcurrncsrow mjcurrncs-data">
的节点代码以及它包含的子节点放入list_soup
里面了。
你可以后面加一句
print(list_soup)
看一看结果。
然后就是难点了,在浏览器上用选定找到我们想要提取的数据。
鼠标点击上面的这行代码,看下图
这些都被选中了,也就证明我们想要的数据在这行代码<div class= "mjrcurrncsrow mjcurrncs-data">
的折叠里。你可以观察到它的子节点都是<div class="mcrow">
这样的。
继续选中下行代码观察
发现了关键点,然后利用下图方法
点击这个按钮(我用的是edge浏览器)
选中美元
蓝色的一行就是我们选中的美元数据所在的代码,但是观察其他的数据
你会发现有很多的同名标签<div class="mcrow">
,这个在爬取很多网站上都会存在的问题
打开另外的同名标签,观察
你会发现这些标签<span>
以及class属性与上一个美元完全相同。
如果我们仅仅用
name = money_info.find("span",class_="cntrycol").get_text("title").strip()
来查询,会只找到美元,而没有其他的数据。同样汇率数据也是如此
因此我们利用for循环
for money_info in soup.find_all('div',class_='mcrow'):
分批处理数据。而money_info是每次利用find
函数查询的结果。显示出<div class="mcrow">
的代码段。
例如第一次循环,money_info是美元子节点的代码
而find_all
是一个跟find
差不多的函数。find_all()
方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件。
find_all()
方法将返回文档中符合条件的所有tag,尽管有时候我们只想得到一个结果.比如文档中只有一个<body>
标签,那么使用find_all()
方法来查找<body>
标签就不太合适,
find
只会输出第一个搜寻结果。
详情用法在官方文档。以上说明也是摘自官方文档。
注意find_all()
返回的是一个包含很多元素的列表,我们使用for依次处理列表中的每一个元素。
接下来分析for
循环中的代码,
第一句
name = money_info.find("span",class_="cntrycol").get_text("title").strip()
money_info其实是BeautifulSoup
解析处理后的对象,就如同上文的soup
和soup_list
一样,然后我们利用find
函数查询美元名称数据位于的节点。这个是需要我们去主动找到我们想要的数据位于哪个节点。然后查询。
"span"
是参数,节点的标签,class_
同样是参数,后面的"cntrycol"
是CSS类名,一样用于确定数据的位置。
而后缀get_text
也是BeautifulSoup
里面的一个函数,
如果只想得到tag中包含的文本内容,那么可以用
get_text()
方法,这个方法获取到tag中包含的所有文本内容包括子tag中的内容,并将结果作为Unicode字符串返回。
在这里我要纠正一个错误,那就是get_text
的参数,不是这样用的。以下是官方文档的说明。
markup = '<a href="http://example.com/">\nI linked to <i>example.com</i>\n</a>' soup = BeautifulSoup(markup) soup.get_text() u'\nI linked to example.com\n' soup.i.get_text() u'example.com'
可以通过参数指定tag的文本内容的分隔符:
# soup.get_text("|") u'\nI linked to |example.com|\n'
还可以去除获得文本内容的前后空白:
# soup.get_text("|", strip=True) u'I linked to|example.com'
因此在我的代码中get_text()
的参数"title"是无效的,去掉也可以。因为在此之前,我们利用find
函数找到的(数据位于的)节点中仅仅只有美元这个文本内容。
且观察文本左右无空白字符和换行字符,因此也不需要.strip()
这个函数后缀。
所以代码也可以这样写
name = money_info.find("span",class_="cntrycol").get_text()
同样的效果。
选中汇率,观察代码。**注意啊!我圈起来的黑色字(在这行代码里唯一显示黑色的)才是文本内容。**而前面的title="美元"
,title="6.4634"
,aria-label="价格 6.4634"
这些是HTML标签的属性。不是文本内容。因此我们使用get_text()
函数获取的是美元以及6.4634。
exchange_rate= money_info.find("span", class_= "pricecol").get_text("aria-label").strip()
这句同理,也可以删除一些无用代码。
exchange_rate= money_info.find("span", class_= "pricecol").get_text()
到此你可以发现对于参数,有时候用双引号""
,有时候用单引号''
。在Python中双引号与单引号可以混用,两者无区别。
然后我们建立一个字典,将数据放进去。然后打印输出。
Money_data = {
'货币': name,
'汇率': exchange_rate
}
打印字典,后面自动会有一个换行符,进行换行。
利用for
循环打印完每一次的字典。
因此最后的代码为
import requests
from bs4 import BeautifulSoup
link = "https://www.msn.cn/zh-cn/money/currencyconverter"#MSN 财经
headers = {'User-Agent' : 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
r = requests.get(link, headers= headers)
soup = BeautifulSoup(r.text, 'html.parser')
list_soup = soup.find("div", class_= "mjrcurrncsrow mjcurrncs-data")
for money_info in soup.find_all('div',class_='mcrow'):
name = money_info.find("span",class_="cntrycol").get_text()
exchange_rate= money_info.find("span", class_= "pricecol").get_text()
Money_data = {
'货币': name,
'汇率': exchange_rate
}
print (Money_data)
结果如下,
虽然不太美观。哈哈。
我们的爬虫就完成了!
当然这只是一个非常非常简单案例。对于一些拥有复杂机制的网站,例如在豆瓣爬取图书信息,由于图书很多,需要翻页,这就需要我们在代码中实现翻页功能,方法嘛也有,但是比较复杂,百度一下你就知道。另外有些网站还需要登录验证,这些当然更复杂,我们需要骗过网站进行验证,还有如果你短时间爬取太多也有可能会被封IP,为了避免这种情况,我们也可以进行IP代理,这些操作起来也很复杂。
最后总结,爬虫其实是一个违法行为。尽量克制。
.