网页抓取数据百度百科( 如何解决网络数据流写入文件时的编码问题(图))

优采云 发布时间: 2022-03-11 00:07

  网页抓取数据百度百科(

如何解决网络数据流写入文件时的编码问题(图))

   前言 <p>本文整理自慕课网 《Python开发简单爬虫》 ,将会记录爬取百度百科“python”词条相关页面的整个过程。 抓取策略

  

  确定目标:确定抓取哪个网站的哪些页面的哪部分数据。本实例抓取百度百科python词条页面以及python相关词条页面的标题和简介。

  分析目标:分析要抓取的url的格式,限定抓取范围。分析要抓取的数据的格式,本实例中就要分析标题和简介这两个数据所在的标签的格式。分析要抓取的页面编码的格式,在网页解析器部分,要指定网页编码,然后才能进行正确的解析。

  编写代码:在网页解析器部分,要使用到分析目标得到的结果。

  执行爬虫:进行数据抓取。 分析目标

  1、url格式

  进入百度百科python词条页面,页面中相关词条的链接比较统一,大都是 /view/xxx.htm 。

  

  2、数据格式

  标题位于类lemmaWgt-lemmaTitle-title下的h1子标签,简介位于类lemma-summary下。

  

  3、编码格式

  查看页面编码格式,为utf-8。

  

  经过以上分析,得到结果如下:

  

代码编写 项目结构

  在sublime下,新建文件夹baike-spider,作为项目根目录。

  新建spider_main.py,作为爬虫总调度程序。

  新建url_manger.py,作为url管理器。

  新建html_downloader.py,作为html下载器。

  新建html_parser.py,作为html解析器。

  新建html_outputer.py,作为写出数据的工具。

  最终项目结构如下图:

  

spider_main.py # coding:utf-8 import url_manager, html_downloader, html_parser, html_outputer   class SpiderMain(object):     def __init__(self):         self.urls = url_manager.UrlManager()         self.downloader = html_downloader.HtmlDownloader()         self.parser = html_parser.HtmlParser()         self.outputer = html_outputer.HtmlOutputer()       def craw(self, root_url):         count = 1         self.urls.add_new_url(root_url)         while self.urls.has_new_url():             try:                 new_url = self.urls.get_new_url()                 print('craw %d : %s' % (count, new_url))                 html_cont = self.downloader.download(new_url)                 new_urls, new_data = self.parser.parse(new_url, html_cont)                 self.urls.add_new_urls(new_urls)                 self.outputer.collect_data(new_data)                   if count == 10:                     break                   count = count + 1             except:                 print('craw failed')           self.outputer.output_html()     if __name__=='__main__':     root_url = 'http://baike.baidu.com/view/21087.htm'     obj_spider = SpiderMain()     obj_spider.craw(root_url) </p>

  url_manger.py

   # coding:utf-8 class UrlManager(object):     def __init__(self):         self.new_urls = set()         self.old_urls = set()       def add_new_url(self, url):         if urlis None:             return         if urlnot in self.new_urlsand urlnot in self.old_urls:             self.new_urls.add(url)       def add_new_urls(self, urls):         if urlsis None or len(urls) == 0:             return         for urlin urls:             self.add_new_url(url)       def has_new_url(self):         return len(self.new_urls) != 0       def get_new_url(self):         new_url = self.new_urls.pop()         self.old_urls.add(new_url)         return new_url

  html_downloader.py

   # coding:utf-8 import urllib.request   class HtmlDownloader(object):     def download(self, url):         if urlis None:             return None         response = urllib.request.urlopen(url)         if response.getcode() != 200:             return None         return response.read()

  html_parser.py

   # coding:utf-8 from bs4import BeautifulSoup import re from urllib.parseimport urljoin   class HtmlParser(object):     def _get_new_urls(self, page_url, soup):         new_urls = set()         # /view/123.htm         links = soup.find_all('a', href=re.compile(r'/view/\d+\.htm'))         for linkin links:             new_url = link['href']             new_full_url = urljoin(page_url, new_url)             # print(new_full_url)             new_urls.add(new_full_url)         #print(new_urls)         return new_urls       def _get_new_data(self, page_url, soup):         res_data = {}         # url         res_data['url'] = page_url         # Python         title_node = soup.find('dd', class_='lemmaWgt-lemmaTitle-title').find('h1')         res_data['title'] = title_node.get_text()         #         summary_node = soup.find('div', class_='lemma-summary')         res_data['summary'] = summary_node.get_text()         # print(res_data)         return res_data       def parse(self, page_url, html_cont):         if page_urlis None or html_contis None:             return         soup = BeautifulSoup(html_cont, 'html.parser')         # print(soup.prettify())         new_urls = self._get_new_urls(page_url, soup)         new_data = self._get_new_data(page_url, soup)         # print('mark')         return new_urls, new_data

  html_outputer.py

   # coding:utf-8 class HtmlOutputer(object):     def __init__(self):         self.datas = []       def collect_data(self, data):         if datais None:             return         self.datas.append(data)       def output_html(self):         fout = open('output.html','w', encoding='utf-8')           fout.write('')         fout.write('')         fout.write('')           for datain self.datas:             fout.write('')             fout.write('%s' % data['url'])             fout.write('%s' % data['title'])             fout.write('%s' % data['summary'])             fout.write('')           fout.write('')         fout.write('')         fout.write('')           fout.close()

  跑步

  在命令行,执行 python spider_main.py 。

  编码问题

  问题描述:UnicodeEncodeError: 'gbk' codec can't encode character 'xa0' in position ...

  在使用Python写文件时,或者将网络数据流写入本地文件时,大多数情况下都会遇到这个问题。网上有很多类似的文章关于如何解决这个问题,但无非就是编码、解码相关,这难道是这个问题的真正原因吗?不。很多时候,我们使用了decode和encode,尝试了各种编码,utf8、utf-8、gbk、gb2312等,所有的编码都试过了,但是还是报错,就是crash。

  windows下写python脚本的时候,编码问题很严重。在将网络数据流写入文件时,我们会遇到几种编码:

  1、#encoding='XXX'

  这里的编码(即python文件第一行的内容)是指python脚本文件本身的编码,无关紧要。只要 XXX 的编码和文件本身相同,就可以工作。

  例如,可以在notepad++的“格式”菜单中设置各种编码。这时需要保证菜单中设置的编码与编码XXX相同。如果不一样,会报错。

  2、网络数据流的编码

  例如,要获得一个网页,网络数据流的编码就是网页的编码。需要使用decode来解码为unicode编码。

  3、目标文件的编码

  将网络数据流写入新文件,写入文件的代码如下:

   fout = open('output.html','w') fout.write(str)

  在windows下,新建文件的默认编码是gbk,python解释器会使用gbk编码来解析我们的网络数据流str,但是str是解码后的unicode编码,会导致解析失败和以上问题。解决方案是更改目标文件的编码:

   fout = open('output.html','w', encoding='utf-8')

  运行结果

  

  

  从:

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线