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)
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
- # <dd class="lemmaWgt-lemmaTitle-title"> <h1>Python</h1>
- title_node = soup.find('dd', class_='lemmaWgt-lemmaTitle-title').find('h1')
- res_data['title'] = title_node.get_text()
- # <div class="lemma-summary" label-module="lemmaSummary">
- 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_url is None or html_cont is 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 data is None:
- return
- self.datas.append(data)
- def output_html(self):
- fout = open('output.html','w', encoding='utf-8')
- fout.write('<html>')
- fout.write('<body>')
- fout.write('<table>')
- for data in self.datas:
- fout.write('<tr>')
- fout.write('<td>%s</td>' % data['url'])
- fout.write('<td>%s</td>' % data['title'])
- fout.write('<td>%s</td>' % data['summary'])
- fout.write('</tr>')
- fout.write('</table>')
- fout.write('</body>')
- fout.write('</html>')
- fout.close()
运行
在命令行下,执行python spider_main.py。
编码问题
问题描述:UnicodeEncodeError: ‘gbk’ codec can’t encode character ‘\xa0’ in position …
使用Python写文件的时候,或者将网络数据流写入到本地文件的时候,大部分情况下会遇到这个问题。网络上有很多类似的文章讲述如何解决这个问题,但是无非就是encode,decode相关的,这是导致该问题出现的真正原因吗?不是的。很多时候,我们使用了decode和encode,试遍了各种编码,utf8,utf-8,gbk,gb2312等等,该有的编码都试遍了,可是仍然出现该错误,令人崩溃。
在windows下面编写python脚本,编码问题很严重。将网络数据流写入文件时,我们会遇到几个编码:
1、#encoding=’XXX’
这里(也就是python文件第一行的内容)的编码是指该python脚本文件本身的编码,无关紧要。只要XXX和文件本身的编码相同就行了。
比如notepad++”格式”菜单里面里可以设置各种编码,这时需要保证该菜单里设置的编码和encoding XXX相同就行了,不同的话会报错。
2、网络数据流的编码
比如获取网页,那么网络数据流的编码就是网页的编码。需要使用decode解码成unicode编码。
3、目标文件的编码
将网络数据流写入到新文件,写文件代码如下:
- fout = open('output.html','w')
- fout.write(str)
在windows下面,新文件的默认编码是gbk,python解释器会用gbk编码去解析我们的网络数据流str,然而str是decode过的unicode编码,这样的话就会导致解析不了,出现上述问题。 解决的办法是改变目标文件的编码:
- fout = open('output.html','w', encoding='utf-8')
Python抓取数据具体流程的更多相关文章
- python抓取数据,python使用socks代理抓取数据
在python中,正常的抓取数据直接使用urllib2 这个模块: import urllib2 url = 'http://fanyi.baidu.com/' stream = urllib2.ur ...
- 在mac下使用python抓取数据
2015已经过去,这是2016的第一篇博文! 祝大家新年快乐! 但是我还有好多期末考试! 还没开始复习,唉,一把辛酸泪! 最近看了一遍彦祖的文章叫做 iOS程序员如何使用Python写网路爬虫 所以自 ...
- python抓取数据 常见反爬虫 情况
1.报文头信息: User-Agent Accept-Language 防盗链 上referer 随机生成不同的User-Agent构造报头 2.加抓取等待时间 每抓取一页都让它随机休息几秒,加入此 ...
- python抓取数据构建词云
1.词云图 词云图,也叫文字云,是对文本中出现频率较高的"关键词"予以视觉化的展现,词云图过滤掉大量的低频低质的文本信息,使得浏览者只要一眼扫过文本就可领略文本的主旨. 先看几个词 ...
- python 抓取数据,pandas进行数据分析并可视化展示
感觉要总结总结了,希望这次能写个系列文章分享分享心得,和大神们交流交流,提升提升. 因为半桶子水的水平,一直在想写什么,为什么写,怎么写. 直到现在找到了一种好的办法: 1.写什么 自己手上掌握的,工 ...
- python 抓取数据 存入 excel
import requestsimport datetimefrom random import choicefrom time import timefrom openpyxl import loa ...
- Python 抓取数据存储到Mysql中
# -*- coding: utf-8 -*- import os,sys import requests import bs4 import pymysql#import MySQLdb #连接MY ...
- Python 抓取数据存储到Redis中
redis是一个key-value存储结构.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set ...
- 使用python抓取数据之菜鸟爬虫1
''' Created on 2018-5-27 @author: yaoshuangqi ''' #本代码获取百度乐彩网站上的信息,只获取最近100期的双色球 import urllib.reque ...
- 使用python抓取并分析数据—链家网(requests+BeautifulSoup)(转)
本篇文章是使用python抓取数据的第一篇,使用requests+BeautifulSoup的方法对页面进行抓取和数据提取.通过使用requests库对链家网二手房列表页进行抓取,通过Beautifu ...
随机推荐
- es 部署 进程、文件数 配置
1. /etc/security/limits.conf elasticsearch soft nofile 65536 elasticsearch hard nofile 65536 elasti ...
- 空间数据格式(地理数据格式):GeoJSON(FeatureCollection)与EsriJSON(FeatureSet/ArcGIS格式)
一.FeatureCollection(GeoJSON)格式介绍 https://learn.microsoft.com/en-us/javascript/api/azure-maps-control ...
- unity 调试 packages
package中代码vs无法f12跳转 解决方法 1 把包copy出来 2 Package Manager->Add package from disk 3 选择包文件中的package.jso ...
- iverilog_makefile
makefile run: iverilog -g2005-sv -I ../inc -s tb -f filelist -o kout sim: vvp kout flist: find ../rt ...
- CentOS网络服务操作命令
CentOS 重启网络服务,输入下面的命令:systemctl retart network.service 或 systemctl restart network.CentOS 启动网络服务,输入下 ...
- 【Java】【Mybatis】如何调用存储过程和存储函数
https://www.jb51.net/article/230756.htm Mybatis调用存储过程 MyBatis支持使用存储过程的配置.当使用存储过程时,需要设置一个参数"mode ...
- 上传镜像到harbor
https://blog.csdn.net/weixin_45335305/article/details/123817541
- Linux下运行jmeter测试案例
主要介绍Jmeter脚本如何在Linux通过no GUI的方式运行 一.Linux下JDK的安装及环境变量的配置(可自行百度安装配置流程,window下安装的Jmeter和JDK要和Linux的保持一 ...
- 043_关于Salesforce集中权限的解释
1.创建Object的时候,一定要选中Deploy,避免在All Tabs 中找不到 2.在Profile里,选择 Standart tab Setting.Custom tab setting,有三 ...
- python爬虫代码中_获取状态码
'两种方式' import urllib status=urllib.urlopen("//www.jb51.net").code print status import requ ...