当前位置: 首页 > 科技观察

Python爬虫入门教程!教你如何爬取网页数据

时间:2023-03-20 16:49:03 科技观察

其实在当今社会,互联网上充斥着大量有用的数据。我们只需要耐心观察,加上一些技术手段,就可以得到很多有价值的数据。这里的“技术手段”就是网络爬虫。今天给大家分享一个爬虫的基础知识和入门教程:什么是爬虫?爬虫是一种自动获取网页内容的程序,比如搜索引擎、谷歌、百度等,每天都运行着庞大的爬虫系统,来自世界各地网站的爬虫数据用于用户检索。爬虫进程实际上是对网络爬虫的抽象。它包括以下步骤:模拟请求网页。模拟浏览器打开目标网站。检索数据。打开网站后,我们可以自动获取我们需要的网站数据。保存数据。获取到数据后,需要持久化到本地文件或数据库等存储设备中。那么我们如何使用Python来编写自己的爬虫程序,这里我想重点介绍一个Python库:Requests。Requests在Python中使用Requests库发起HTTP请求,非常方便简单易用。模拟发送HTTP请求发送GET请求当我们用浏览器打开豆瓣首页时,发送的最原始的请求是GET请求importrequestsres=requests.get('http://www.douban.com')print(res)print(type(res))>>>可以看到我们得到的是一个Response对象。如果我们要获取网站返回的数据,可以使用text或者content属性获取text:以字符串形式返回数据content:以二进制形式返回数据print(type(res.text))print(res.text)>>>.....发送POST请求POST请求一般是提交一个表单r=requests.post('http://www.xxxx.com',data={"key":"value"})data,也就是需要传递的表单信息,是字典类型的数据。Headerenhancement对于一些网站,没有header的请求会被拒绝,所以需要进行一些header增强。例如:UA、Cookie、host等信息。header={"User-Agent":"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/76.0.3809.100Safari/537.36","Cookie":"yourcookie"}res=requests.get('http://www.xxx.com',headers=header)解析HTML现在我们已经拿到了网页返回的数据,也就是HTML代码,我们需要解析HTML来提取有效信息。BeautifulSoupBeautifulSoup是Python的一个库,主要功能是解析网页中的数据。frombs4importBeautifulSoup#导入BeautifulSoup方法#可以传入字符串或者文件句柄。一般都是先用requests库获取网页内容,然后用soup解析。soup=BeautifulSoup(html_doc,'html.parser')#这里必须指定解析器,可以使用默认的html,也可以使用lxml。print(soup.prettify())#按照标准缩进格式输出得到的汤内容。BeautifulSoup的一些简单用法print(soup.title)#获取文档的标题print(soup.title.name)#获取标题的name属性print(soup.title.string)#获取标题的内容print(soup.p)#获取文档中的第一个p节点print(soup.p['class'])#获取第一个p节点的class内容print(soup.find_all('a'))#获取所有的文档中的一个节点并返回一个listprint(soup.find_all('span',attrs={'style':"color:#ff0000"}))#获取文档中所有span和style符合规则的节点,并返回一个列表,具体的用法和效果,我在后面的实战中会详细说明。XPath定位XPath是XML的路径语言,用于通过元素和属性进行导航和定位。几个常用的表达表达含义nodeselectallchildnodesofthenodenode/selectsfromtherootnode//selectsallcurrentnodes。currentnode..parentnode@attributeselecttext()当前路径下的文本内容somesimpleExamplexpath('node')#选择node节点的所有子节点xpath('/div')#从根节点xpath中选择div元素('//div')#选择所有div元素xpath('./div')#选择当前节点下的div元素xpath('//@id')#选择所有有id属性的节点当然XPath是非常强大,但是语法比较复杂,不过我们可以通过Chrome的开发者工具快速定位到该元素的xpath,如下图,是//*[@id="anony-nav"]/div[1]/ul/li[1]/a在实际使用中,是用BeautifulSoup还是XPath,全看个人喜好,哪个更熟练,用起来更方便,就用哪个。爬虫实战:爬取豆瓣海报我们可以从豆瓣电影页面进入豆瓣对应的电影页面,例如以刘涛为例,她的电影页面地址是https://movie.douban.com/celebrity/1011562/photos/接下来我们来分析一下这个网页目标网站页面分析注意:互联网上的网站页面构成总是会变的,所以这里需要学习分析的方法,等到其他网站。俗话说,授人以鱼不如授人以渔,就是这个道理。ChromeDeveloperToolsChromeDeveloperTools(按F12打开)是分析网页的优秀工具,一定要用好。我们在任意一张图片上右击,选择“Inspect”,可以看到“DeveloperTools”也打开了,自动定位到了图片所在的位置。可以清楚的看到每张图片都保存在li标签中,图片的地址保存在li标签中的img中。知道这些规则后,我们就可以通过BeautifulSoup或者XPath来解析HTML页面,获取其中的图片地址。代码编写我们只需要几行代码就可以完成图片url的提取importrequestsfrombs4importBeautifulSouurl='https://movie.douban.com/celebrity/1011562/photos/'res=requests.get(url).textcontent=BeautifulSoup(res,"html.parser")data=content.find_all('div',attrs={'class':'cover'})picture_list=[]fordindata:plist=d.find('img')['src']picture_list.append(plist)print(picture_list)>>>['https://img1.doubanio.com/view/photo/m/public/p2564834267.jpg','https://img1.doubanio.com/view/photo/m/public/p860687617.jpg','https://img1.doubanio.com/view/photo/m/public/p2174001857.jpg','https://img1.doubanio.com/view/photo/m/public/p1563789129.jpg','https://img3.doubanio.com/view/photo/m/public/p2363429946.jpg','https://img1.doubanio.com/view/photo/m/public/p2382591759.jpg','https://img3.doubanio.com/view/photo/m/public/p2363269182.jpg','https://img1.doubanio.com/view/photo/m/public/p1959495269.jpg','https://img3.doubanio.com/view/photo/m/public/p2356638830.jpg','https://img3.doubanio.com/view/photo/m/public/p1959495471.jpg','https://img3.doubanio.com/view/photo/m/public/p1834379290.jpg','https://img3.doubanio.com/view/photo/m/public/p2325385303.jpg','https://img3.doubanio.com/view/photo/m/public/p2361707270.jpg','https://img3.doubanio.com/view/photo/m/public/p2325385321.jpg','https://img3.doubanio.com/view/photo/m/public/p2196488184.jpg','https://img1.doubanio.com/view/photo/m/public/p2186019528.jpg','https://img1.doubanio.com/view/photo/m/public/p2363270277.jpg','https://img3.doubanio.com/view/photo/m/public/p2325240501.jpg','https://img1.doubanio.com/view/photo/m/public/p2258657168.jpg','https://img1.doubanio.com/view/photo/m/public/p2319710627.jpg','https://img3.doubanio.com/view/photo/m/public/p2319710591.jpg','https://img3.doubanio.com/view/photo/m/public/p2311434791.jpg','https://img1.doubanio.com/view/photo/m/public/p2363270708.jpg','https://img3.doubanio.com/view/photo/m/public/p2258657185.jpg','https://img3.doubanio.com/view/photo/m/public/p2166193915.jpg','https://img3.doubanio.com/view/photo/m/public/p2363265595.jpg','https://img3.doubanio.com/view/photo/m/public/p2312085755.jpg','https://img3.doubanio.com/view/photo/m/public/p2311434790.jpg','https://img3.doubanio.com/view/photo/m/public/p2276569205.jpg','https://img1.doubanio.com/view/photo/m/public/p2165332728.jpg']可以看到是一个很干净的列表,里面存储了发帖人地址,不过这里只有一页发帖人资料。我们观察页面,发现页面很多。如何处理分页符。分页处理,我们点击第二页查看浏览器urlhttps://movie.douban.com/celebrity/1011562/photos/?type=C&start=30&sortby=like&size=a&subtype=a的变化,发现浏览器url增加了几个点击第三页第一个参数,继续观察urlhttps://movie.douban.com/celebrity/1011562/photos/?type=C&start=60&sortby=like&size=a&subtype=a通过观察,我们可以看出,这里的参数只是start变化的,都是变量,其余参数按常理处理即可。同时可以知道start参数应该起到类似page的作用,start=30是第二页,start=60是第三页,以此类推,最后一页是start=420.这样我们处理分页的代码就可以出来了。首先将上面处理HTML页面的代码封装成一个函数defget_poster_url(res):content=BeautifulSoup(res,"html.parser")data=content.find_all('div',attrs={'class':'cover'})picture_list=[]fordindata:plist=d.find('img')['src']picture_list.append(plist)returnpicture_list然后我们处理分页并在另一个函数中调用上面的函数deffire():page=0foriinrange(0,450,30):print("开始抓取页面%s"%page)url='https://movie.douban.com/celebrity/1011562/photos/?type=C&start={}&sortby=like&size=a&subtype=a'.format(i)res=requests.get(url).textdata=get_poster_url(res)page+=1此时,我们所有的海报数据都存储在data变量中,现在我们需要一个下载器来保存海报defdownload_picture(pic_l):ifnotos.path.exists(r'picture'):os.mkdir(r'picture')foriinpic_l:pic=requests.get(i)p_name=i.split('/')[7]withopen('picture\\'+p_name,'wb')asf:f.write(pic.content)然后把下载器添加到fire函数中,以免请求太频繁影响正常访问豆瓣,设置休眠时间为1秒defire():page=0foriinrange(0,450,30):print("开始爬取页面%s"%page)url='https://movie.douban.com/celebrity/1011562/照片/?type=C&start={}&sortby=like&size=a&subtype=a'.format(i)res=requests.get(url).textdata=get_poster_url(res)download_picture(data)page+=1time.sleep(1)执行fire下面的函数,程序运行完毕后,会在当前目录下生成一个图片文件夹,里面存放了我们下载的海报的所有核心代码。下面看完整代码importrequestsfrombs4importBeautifulSoupimporttimeimportosdefire():page=0foriinrange(0,450,30):print("开始抓取页面%s"%page)url='https://movie.douban.com/celebrity/1011562/photos/?type=C&start={}&sortby=like&size=a&subtype=a'.format(i)res=requests.get(url).textdata=get_poster_url(res)download_picture(data)page+=1time.sleep(1)defget_poster_url(res):content=BeautifulSoup(res,"html.parser")data=content.find_all('div',attrs={'class':'cover'})picture_list=[]fordindata:plist=d.find('img')['src']picture_list.append(plist)returnpicture_listdefdownload_picture(pic_l):ifnotos.path.exists(r'picture'):os.mkdir(r'picture')foriinpic_l:pic=requests.get(i)p_name=i.split('/')[7]withopen('图片\'+p_name,'wb')asf:f.write(pic.content)if__name__=='__main__':fire()firefunction这是一个主执行函数,使用range函数处理分页range函数可以快速创建列表整数,它在for循环中非常有用。函数中的0表示从0开始计数,450表示一直迭代到450,不包括450,30表示步长,即每次递增的数字间隔。range(0,450,30),会依次输出:0,30,60,90...format函数是一种字符串格式化方法。time.sleep(1)是暂停1秒。get_poster_url函数是解析HTML函数使用BeautifulSoup通过find_all方法找到所有类为“cover”的div元素,并返回一个列表。使用for循环循环遍历上一步得到的列表,取出src的内容,追加到列表中。append是list的一种方法,可以在list后面添加元素download_picture函数。简易图片下载器首先判断当前目录下是否有图片文件夹。os.path.existsos库是一个非常常用的与操作系统相关的命令库。os.mkdir是创建一个文件夹split来剪切字符串,取出标有7的元素,作为存储图像的名称。with方法用于快速打开文件。打开的进程可以自行关闭文件句柄,不再需要手动执行f.close()关闭文件总结本节讲解爬虫的基本流程和需要用到的Python库和方法,完成通过一个实例,从分析网页到数据存储的全过程。其实爬虫无非就是模拟请求、解析数据、保存数据。当然,有时候,网站也会设置各种反爬机制,比如cookie验证、请求频率检查、非浏览器访问限制、JS混淆等,这时候就需要用到反爬技术了,比如抓取cookie放到headers中,使用代理IP访问,使用Selenium模拟浏览器等待模式。由于本课程不是专门的爬虫类,所以这些技巧就留给自己去摸索吧。