算法的实现先暂时告一段落,最近有些忙。下面介绍一下最近在干的东西---数据挖掘之数据获取之爬虫。
爬虫:网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。其主要目的就是爬取一定的数据。
本次的爬虫,目的是爬取美国的国情咨文。这个网站http://www.presidency.ucsb.edu/sou.php有一些国情咨文。因此,就从这个网站入手,爬取一下1920年到1949年的国情咨文。
打开网页国情咨文的网页,用Google浏览器检查代码,可以发现:2013年的国情咨文的连接是:http://www.presidency.ucsb.edu/ws/index.php?pid=102826 之后打开其他咨文的连接,可以发现,在href中均有pid的出现,因此我们就利用这个来进行正则匹配爬取连接。
爬到连接后,下一步是要访问所爬取的连接。我们在上一步当中,将爬取的年份和连接存入到字典当中,这样就可以遍历字典,从而遍历访问每一年的连接。
我们首先打开13年的连接,查看他的元素。
可以发现,每个连接中的正文都是放在了span的标签当中,这个特点就成为我们爬这个正文的关键点。
明白了大致思路后,下面我们就开始上代码。
import re
from bs4 import BeautifulSoup
import requests
import openpyxl
import datetime
class pachong:
def set_path(self,path):
self.path = path
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.63 Safari/537.36'}
def get_url(self,url):
html = requests.get(url, self.headers).content
bsobj = BeautifulSoup(html, "html.parser", from_encoding="utf-8")
return bsobj
def get_links(self,value):
links = value.find_all("a", href=re.compile("pid"), text=re.compile('19[2-4]'))
url = {}
for i in range(len(links)):
url[str(links[i].contents[0])] = str(links[i].attrs['href'])
return url
def get_text(self,url):
bsobj=self.get_url(url)
cont = bsobj.find_all('span', class_=re.compile("displaytext"))
for con in cont:
text = con.find_all('p') # 在每个标签下查找p标签
file = ""
for i in range(len(text)):
file += str(text[i].contents[0])
return file
def save_xls(self,i,f,year,file ):
sheet1=f.active
sheet1["A%d" % (i)].value =year
sheet1["B%d" % (i)].value = file
if __name__ == '__main__':
starttime = datetime.datetime.now()
p = pachong()
print("请输入存储路径:")
path=input()
p.set_path(path)
print("开始检索数据。。。。")
link_list=p.get_links(p.get_url("http://www.presidency.ucsb.edu/sou.php"))
i = 1
f = openpyxl.Workbook() # 创建工作簿
for key in link_list:
year=key
print(key,link_list[key])
file=p.get_text(link_list[key])
p.save_xls(i,f,year,file)
i+=1
f.save(p.path)
endtime = datetime.datetime.now()
print("程序运行时间"+str(endtime - starttime))
代码比较简单易懂。说几个入坑的地方:
1、find_all()函数返回的是一个ResultSet 也就是一个集合,类似于数组,通过索引可以查看每个元素的值,是不同于find()函数的。所以,返回的返回的数据比较多,而且有一些没用的标签也进来了。
如果你使用了find_all()函数,恭喜你,中奖了。你需要对find_all返回的对象进行一定的处理。
1)find_all 有两个常用的参数,一个是attrs,一个是contents。
通过attrs,返回的是这个标签里面的属性。使用attrs['href']就可以获得返回对象中href的连接了
contents 就是获取标签中所有的内容。比如,你使用find_all('p')查找p标签,那么会返回所找到的p标签的中的所有内容。因此,想要准确活动contents,就需要好的正则表达。
2)接着上面的问题,如果你并没有能够很准确匹配出关键信息,而且里面又包含了很多没有用的标签,或者像这个例子中一样,文本用多个p标签分割开来。那么就需要进一步处理。那么如何处理呢?就是对第一次find的结果在进行find。原理相同,这时候再处理就方便了很多。
3) 往excel储存的时候,可能会遇到这样的问题,提示字符超出限制了。那说明,你的包用错了。建议换成openpyxl。这个包会解决这个问题。
拓展:有个这个爬虫基础,我觉得再爬其他的网页就相对简单了,都是一个思路,只要准确分析好网页的特点,写好对应的正则表达式就可以了。当然,这个爬虫也有很大的缺点,就是爬取得深度为1.。如果文中还有其他的连接,不能够遍历访问。这个问题等最近有空再去思考一下该怎么解决。