网页抓取数据百度百科(抓取策略确定目标:确定抓取哪个网站的哪些页面的哪部分数据)

优采云 发布时间: 2021-12-18 07:01

  网页抓取数据百度百科(抓取策略确定目标:确定抓取哪个网站的哪些页面的哪部分数据)

  爬取策略

  

  确定目标:确定要抓取哪个网站的哪个页面的哪一部分数据。本例抓取百度百科python入口页面和python相关入口页面的标题和介绍。

  分析目标:分析要爬取的URL的格式,限制爬取的范围。分析要捕获的数据的格式。在本例中,我们将分析标题和介绍这两个数据所在的标签格式。分析要爬取的页面编码的格式。在页面解析器部分,您必须指定页面编码才能进行正确的分析。

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

  执行爬虫:数据抓取。

  分析目标

  1、网址格式

  进入百度百科的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 作为写出数据的工具。

  最终的项目结构如下:

  

  蜘蛛主.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)

  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 url is None:

return

if url not in self.new_urls and url not in self.old_urls:

self.new_urls.add(url)

def add_new_urls(self, urls):

if urls is None or len(urls) == 0:

return

for url in 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 url is None:

return None

response = urllib.request.urlopen(url)

if response.getcode() != 200:

return None

return response.read()

  html_parser.py

  # coding:utf-8

from bs4 import BeautifulSoup

import re

from urllib.parse import 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 link in 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()

# <p class="lemma-summary" label-module="lemmaSummary">

summary_node = soup.find(&#39;p&#39;, class_=&#39;lemma-summary&#39;)

res_data[&#39;summary&#39;] = summary_node.get_text()

# print(res_data)

return res_data

def parse(self, page_url, html_cont):

if page_url is None or html_cont is None:

return

soup = BeautifulSoup(html_cont, &#39;html.parser&#39;)

# print(soup.prettify())

new_urls = self._get_new_urls(page_url, soup)

new_data = self._get_new_data(page_url, soup)

# print(&#39;mark&#39;)

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 data is None:

return

self.datas.append(data)

def output_html(self):

fout = open(&#39;output.html&#39;,&#39;w&#39;, encoding=&#39;utf-8&#39;)

fout.write(&#39;&#39;)

fout.write(&#39;&#39;)

fout.write(&#39;&#39;)

for data in self.datas:

fout.write(&#39;&#39;)

fout.write(&#39;%s&#39; % data[&#39;url&#39;])

fout.write(&#39;%s&#39; % data[&#39;title&#39;])

fout.write(&#39;%s&#39; % data[&#39;summary&#39;])

fout.write(&#39;&#39;)

fout.write(&#39;&#39;)

fout.write(&#39;&#39;)

fout.write(&#39;&#39;)

fout.close()

  跑

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

  编码问题

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

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

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

  1、#encoding='XXX'

  这里的编码(即python文件第一行的内容)是指python脚本文件本身的编码,无所谓。只要XXX的编码和文件本身是一样的。

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

  2、网络数据流的编码

  比如获取一个网页,那么网络数据流的编码就是网页的编码。需要使用decode解码成unicode编码。

  3、目标文件的编码

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

  fout = open(&#39;output.html&#39;,&#39;w&#39;)

fout.write(str)

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

  fout = open(&#39;output.html&#39;,&#39;w&#39;, encoding=&#39;utf-8&#39;)

  操作结果

  

  

  更多Python抓取百度百科数据文章,请关注PHP中文网!

  

  免责声明:本文原创发表于php中文网。转载请注明出处。感谢您的尊重!如果您有任何疑问,请与我们联系

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线