网站首页 >> 游戏攻略 >> 正文
简介: 以经典的爬取豆瓣电影Top250信息为例。每条电影信息在olclass为grid_view下的li标签里,获取到所有li标签的内容,然后遍历,就可以从中提取出每一条电影的信息。第1页:https://

数据清洗,爬虫解析提取数据的四种方法

以经典的爬取豆瓣电影Top250信息为例。每条电影信息在olclass为grid_view下的li标签里,获取到所有li标签的内容,然后遍历,就可以从中提取出每一条电影的信息。

第1页:https://movie.douban.com/top250?start=0&filter=\n第2页:https://movie.douban.com/top250?start=25&filter=\n第3页:https://movie.douban.com/top250?start=50&filter=\n第10页:https://movie.douban.com/top250?start=225&filter=\n

start参数控制翻页,start=25*(page-1)

本文分别利用正则表达式、BeautifulSoup、PyQuery、Xpath来解析提取数据,并将豆瓣电影Top250信息保存到本地。

正则表达式是一个特殊的字符序列,它能帮助你方便地检查一个字符串是否与某种模式匹配,常用于数据清洗,也可以顺便用于爬虫,从网页源代码文本中匹配出我们想要的数据。

importre\ntext="""\n<divclass="boxpicblockcol3"style="width:186px;height:264px">\n<imgsrc2="http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26584_s.jpg"123nfsjgnalt="山水风景摄影图片">\n<atarget="_blank"href="http://sc.chinaz.com/tupian/200509002684.htm"\n<imgsrc2="http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26518_s.jpg"enrberonbialt="山脉湖泊山水风景图片">\n<atarget="_blank"href="http://sc.chinaz.com/tupian/200509002684.htm"\n<imgsrc2="http://pic2.sc.chinaz.com/Files/pic/pic9/202006/apic26029_s.jpg"woenigoigniefnirneialt="旅游景点山水风景图片">\n<atarget="_blank"href="http://sc.chinaz.com/tupian/200509002684.htm"\n"""\n\npattern=re.compile(r'\\d+')#查找所有数字\nresult1=pattern.findall('me123rich456money1000000000000')\nprint(result1)\nimg_info=re.findall('<imgsrc2="(.*?)".*alt="(.*?)">',text)#匹配src2alt里的内容\n\nforsrc,altinimg_info:\nprint(src,alt)\n\n['123','456','1000000000000']\nhttp://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26584_s.jpg山水风景摄影图片\nhttp://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26518_s.jpg山脉湖泊山水风景图片\nhttp://pic2.sc.chinaz.com/Files/pic/pic9/202006/apic26029_s.jpg旅游景点山水风景图片\n

代码如下:

#-*-coding:UTF-8-*-\n"""\n@Author:叶庭云\n@公众号:修炼Python\n@CSDN:https://yetingyun.blog.csdn.net/\n"""\nimportrequests\nimportre\nfrompandasimportDataFrame\nfromfake_useragentimportUserAgent\nimportlogging\n\n#日志输出的基本配置\nlogging.basicConfig(level=logging.INFO,format='%(asctime)s-%(levelname)s:%(message)s')\n#随机产生请求头\nua=UserAgent(verify_ssl=False,path='fake_useragent.json')\n\n\ndefrandom_ua():\nheaders={\n"Accept-Encoding":"gzip",\n"Connection":"keep-alive",\n"User-Agent":ua.random\n}\nreturnheaders\n\n\ndefscrape_html(url):\nresp=requests.get(url,headers=random_ua())\n#print(resp.status_code,type(resp.status_code))\nifresp.status_code==200:\nreturnresp.text\nelse:\nlogging.info('请求网页失败')\n\n\ndefget_data(page):\nurl=f"https://movie.douban.com/top250?start={25*page}&filter="\nhtml_text=scrape_html(url)\n#电影名称导演主演\nname=re.findall('<imgwidth="100"alt="(.*?)"src=".*"',html_text)\ndirector_actor=re.findall('(.*?)<br>',html_text)\ndirector_actor=[item.strip()foritemindirector_actor]\n#上映时间上映地区电影类型信息去除两端多余空格\ninfo=re.findall('(.*)/(.*)/(.*)',html_text)\ntime_=[x[0].strip()forxininfo]\narea=[x[1].strip()forxininfo]\ngenres=[x[2].strip()forxininfo]\n#评分评分人数\nrating_score=re.findall('<spanclass="rating_num"property="v:average">(.*)</span>',html_text)\nrating_num=re.findall('<span>(.*?)人评价</span>',html_text)\n#一句话引言\nquote=re.findall('<spanclass="inq">(.*)</span>',html_text)\ndata={'电影名':name,'导演和主演':director_actor,\n'上映时间':time_,'上映地区':area,'电影类型':genres,\n'评分':rating_score,'评价人数':rating_num,'引言':quote}\ndf=DataFrame(data)\nifpage==0:\ndf.to_csv('movie_data2.csv',mode='a+',header=True,index=False)\n\nelse:\ndf.to_csv('movie_data2.csv',mode='a+',header=False,index=False)\nlogging.info(f'已爬取第{page+1}页数据')\n\n\nif__name__=='__main__':\nforiinrange(10):\nget_data(i)\n

结果如下:

find()与find_all()是BeautifulSoup对象的两个 *** ,它们可以匹配html的标签和属性,把BeautifulSoup对象里符合要求的数据都提取出来:

#-*-coding:UTF-8-*-\n"""\n@Author:叶庭云\n@公众号:修炼Python\n@CSDN:https://yetingyun.blog.csdn.net/\n"""\nimportrequests\nfrombs4importBeautifulSoup\nimportopenpyxl\nfromfake_useragentimportUserAgent\nimportlogging\n\n#日志输出的基本配置\nlogging.basicConfig(level=logging.INFO,format='%(asctime)s-%(levelname)s:%(message)s')\n#随机产生请求头\nua=UserAgent(verify_ssl=False,path='fake_useragent.json')\nwb=openpyxl.Workbook()#创建工作簿对象\nsheet=wb.active#获取工作簿的活动表\nsheet.title="movie"#工作簿重命名\nsheet.append(["排名","电影名","导演和主演","上映时间","上映地区","电影类型","评分","评价人数","引言"])\n\n\ndefrandom_ua():\nheaders={\n"Accept-Encoding":"gzip",\n"Connection":"keep-alive",\n"User-Agent":ua.random\n}\nreturnheaders\n\n\ndefscrape_html(url):\nresp=requests.get(url,headers=random_ua())\n#print(resp.status_code,type(resp.status_code))\nifresp.status_code==200:\nreturnresp.text\nelse:\nlogging.info('请求网页失败')\n\n\ndefget_data(page):\nglobalrank\nurl=f"https://movie.douban.com/top250?start={25*page}&filter="\nhtml_text=scrape_html(url)\nsoup=BeautifulSoup(html_text,'html.parser')\nlis=soup.find_all('div',class_='item')\nforliinlis:\nname=li.find('div',class_='hd').a.span.text\ntemp=li.find('div',class_='bd').p.text.strip().split('\\n')\ndirector_actor=temp[0]\ntemp1=temp[1].rsplit('/',2)\ntime_,area,genres=[item.strip()foritemintemp1]\nquote=li.find('p',class_='quote')\n#有些电影信息没有一句话引言\nifquote:\nquote=quote.span.text\nelse:\nquote=None\nrating_score=li.find('span',class_='rating_num').text\nrating_num=li.find('div',class_='star').find_all('span')[-1].text\nsheet.append([rank,name,director_actor,time_,area,genres,rating_score,rating_num,quote])\nlogging.info([rank,name,director_actor,time_,area,genres,rating_score,rating_num,quote])\nrank+=1\n\n\nif__name__=='__main__':\nrank=1\nforiinrange(10):\nget_data(i)\nwb.save(filename='movie_info4.xlsx')\n

结果如下:

如下示例:在解析HTML文本的时候,首先需要将其初始化为一个pyquery对象。它的初始化方式有多种,比如直接传入字符串、传入URL、传入文件名等等。

frompyqueryimportPyQueryaspq\n\nhtml='''\n<div>\n<ulclass="clearfix">\n<liclass="item-0">firstitem</li>\n<liclass="item-1"><ahref="link2.html">seconditem</a></li>\n<li><imgsrc="http://pic.netbian.com/uploads/allimg/210107/215736-1610027856f6ef.jpg"></li>\n<li><imgsrc="http://pic.netbian.com//uploads/allimg/190902/152344-1567409024af8c.jpg"></li>\n</ul>\n</div>\n'''\n\ndoc=pq(html)\nprint(doc('li'))\n

结果如下:

<liclass="item-0">firstitem</li>\n<liclass="item-1"><ahref="link2.html">seconditem</a></li>\n<li><imgsrc="http://pic.netbian.com/uploads/allimg/210107/215736-1610027856f6ef.jpg"/></li>\n<li><imgsrc="http://pic.netbian.com//uploads/allimg/190902/152344-1567409024af8c.jpg"/></li>\n

首先引入pyquery这个对象,取别名为pq,然后定义了一个长HTML字符串,并将其当作参数传递给pyquery类,这样就成功完成了初始化。接下来,将初始化的对象传入CSS选择器。在这个实例中,我们传入li节点,这样就可以选择所有的li节点。

#-*-coding:UTF-8-*-\n"""\n@Author:叶庭云\n@公众号:修炼Python\n@CSDN:https://yetingyun.blog.csdn.net/\n"""\nimportrequests\nfrompyqueryimportPyQueryaspq\nimportopenpyxl\nfromfake_useragentimportUserAgent\nimportlogging\n\n#日志输出的基本配置\nlogging.basicConfig(level=logging.INFO,format='%(asctime)s-%(levelname)s:%(message)s')\n#随机产生请求头\nua=UserAgent(verify_ssl=False,path='fake_useragent.json')\nwb=openpyxl.Workbook()#创建工作簿对象\nsheet=wb.active#获取工作簿的活动表\nsheet.title="movie"#工作簿重命名\nsheet.append(["排名","电影名","导演和主演","上映时间","上映地区","电影类型","评分","评价人数","引言"])\n\n\ndefrandom_ua():\nheaders={\n"Accept-Encoding":"gzip",\n"Connection":"keep-alive",\n"User-Agent":ua.random\n}\nreturnheaders\n\n\ndefscrape_html(url):\nresp=requests.get(url,headers=random_ua())\n#print(resp.status_code,type(resp.status_code))\nifresp.status_code==200:\nreturnresp.text\nelse:\nlogging.info('请求网页失败')\n\n\ndefget_data(page):\nglobalrank\nurl=f"https://movie.douban.com/top250?start={25*page}&filter="\nhtml_text=scrape_html(url)\ndoc=pq(html_text)\nlis=doc('.grid_viewli')\nforliinlis.items():\nname=li('.hdaspan:first-child').text()\ntemp=li('.bdp:first-child').text().split('\\n')\ndirector_actor=temp[0]\ntemp1=temp[1].rsplit('/',2)\ntime_,area,genres=[item.strip()foritemintemp1]\nquote=li('.quotespan').text()\nrating_score=li('.star.rating_num').text()\nrating_num=li('.starspan:last-child').text()\nsheet.append([rank,name,director_actor,time_,area,genres,rating_score,rating_num,quote])\nlogging.info([rank,name,director_actor,time_,area,genres,rating_score,rating_num,quote])\nrank+=1\n\n\nif__name__=='__main__':\nrank=1\nforiinrange(10):\nget_data(i)\nwb.save(filename='movie_info3.xlsx')\n

结果如下:

Xpath是一个非常好用的解析 *** ,同时也作为爬虫学习的基础,在后面的Selenium以及Scrapy框架中也会涉及到这部分知识。

首先我们使用lxml的etree库,然后利用etree.HTML初始化,然后我们将其打印出来。其中,这里体现了lxml的一个非常实用的功能就是自动修正html代码,大家应该注意到了,最后一个li标签,其实我把尾标签删掉了,是不闭合的。不过,lxml因为继承了libxml2的特性,具有自动修正HTML代码的功能,通过xpath表达式可以提取标签里的内容,如下所示:

fromlxmlimportetree\ntext='''\n<div>\n<ul>\n<liclass="item-0"><ahref="link1.html">firstitem</a></li>\n<liclass="item-1"><ahref="link2.html">seconditem</a></li>\n<liclass="item-inactive"><ahref="link3.html">thirditem</a></li>\n<liclass="item-1"><ahref="link4.html">fourthitem</a></li>\n<liclass="item-0"><ahref="link5.html">fifthitem</a>\n</ul>\n</div>\n'''\nhtml=etree.HTML(text)\nresult=etree.tostring(html)\nresult1=html.xpath('//li/@class')#xpath表达式\nprint(result1)\nprint(result)\n

['item-0','item-1','item-inactive','item-1','item-0']\n<html><body>\n<div>\n<ul>\n<liclass="item-0"><ahref="link1.html">firstitem</a></li>\n<liclass="item-1"><ahref="link2.html">seconditem</a></li>\n<liclass="item-inactive"><ahref="link3.html">thirditem</a></li>\n<liclass="item-1"><ahref="link4.html">fourthitem</a></li>\n<liclass="item-0"><ahref="link5.html">fifthitem</a></li>\n</ul>\n</div>\n</body></html>\n

代码如下:

#-*-coding:UTF-8-*-\n"""\n@Author:叶庭云\n@公众号:修炼Python\n@CSDN:https://yetingyun.blog.csdn.net/\n"""\nimportrequests\nfromlxmlimportetree\nimportopenpyxl\nfromfake_useragentimportUserAgent\nimportlogging\n\n#日志输出的基本配置\nlogging.basicConfig(level=logging.INFO,format='%(asctime)s-%(levelname)s:%(message)s')\n#随机产生请求头\nua=UserAgent(verify_ssl=False,path='fake_useragent.json')\nwb=openpyxl.Workbook()#创建工作簿对象\nsheet=wb.active#获取工作簿的活动表\nsheet.title="movie"#工作簿重命名\nsheet.append(["排名","电影名","导演和主演","上映时间","上映地区","电影类型","评分","评价人数","引言"])\n\n\ndefrandom_ua():\nheaders={\n"Accept-Encoding":"gzip",\n"Connection":"keep-alive",\n"User-Agent":ua.random\n}\nreturnheaders\n\n\ndefscrape_html(url):\nresp=requests.get(url,headers=random_ua())\n#print(resp.status_code,type(resp.status_code))\nifresp.status_code==200:\nreturnresp.text\nelse:\nlogging.info('请求网页失败')\n\n\ndefget_data(page):\nglobalrank\nurl=f"https://movie.douban.com/top250?start={25*page}&filter="\nhtml=etree.HTML(scrape_html(url))\nlis=html.xpath('//ol[@class="grid_view"]/li')\n#每个li标签里有每部电影的基本信息\nforliinlis:\nname=li.xpath('.//div[@class="hd"]/a/span[1]/text()')[0]\ndirector_actor=li.xpath('.//div[@class="bd"]/p/text()')[0].strip()\ninfo=li.xpath('.//div[@class="bd"]/p/text()')[1].strip()\n#按"/"切割成列表\n_info=info.split("/")\n#得到上映时间上映地区电影类型信息去除两端多余空格\ntime_,area,genres=_info[0].strip(),_info[1].strip(),_info[2].strip()\n#print(time,area,genres)\nrating_score=li.xpath('.//div[@class="star"]/span[2]/text()')[0]\nrating_num=li.xpath('.//div[@class="star"]/span[4]/text()')[0]\nquote=li.xpath('.//p[@class="quote"]/span/text()')\n#有些电影信息没有一句话引言加条件判断防止报错\niflen(quote)==0:\nquote=None\nelse:\nquote=quote[0]\nsheet.append([rank,name,director_actor,time_,area,genres,rating_score,rating_num,quote])\nlogging.info([rank,name,director_actor,time_,area,genres,rating_score,rating_num,quote])\nrank+=1\n\n\nif__name__=='__main__':\nrank=1\nforiinrange(10):\nget_data(i)\nwb.save(filename='movie_info1.xlsx')\n

结果如下:

对于爬取网页结构简单的Web页面,有些代码是可以复用的,如下所示:

fromfake_useragentimportUserAgent\n\n#随机产生请求头\nua=UserAgent(verify_ssl=False,path='fake_useragent.json')\n\ndefrandom_ua():\nheaders={\n"Accept-Encoding":"gzip",\n"User-Agent":ua.random\n}\nreturnheaders\n

伪装请求头,并可以随机切换,封装为函数,便于复用。

defscrape_html(url):\nresp=requests.get(url,headers=random_ua())\n#print(resp.status_code,type(resp.status_code))\n#print(resp.text)\nifresp.status_code==200:\nreturnresp.text\nelse:\nlogging.info('请求网页失败')\n

请求网页,返回状态码为200说明能正常请求,并返回网页源代码文本。

https://docs.python.org/3/library/re.html

https://pyquery.readthedocs.io/en/latest/

https://shimo.im/docs/Gw3GTP8JrTqrCrKQ/

网友点评

博博常识网

博博常识网

www.kissing2lips.com

日常生活里,经常会碰到一些五花八门的小困难。不过好久好在有困难就有方法,如果你足够的细心,你会发现这些小困难都有着对应的小方法。

Powered By Z-BlogPHP Theme By . 鲁ICP备2021032584号-5