实例3–股票数据定向爬虫
程序结构如下:
1.先从网站中获取股票代号列表(requests库,re库)
2.遍历每一只股票,从股票信息网站中获得详细信息
3.使用字典的数据结构,写入文本文件中
更多的内容学习 点我
以下为代码:
1 # 股票数据定向爬虫 2 """ 3 Created on Thu Oct 12 16:12:48 2017 4 5 @author: DONG LONG RUI 6 """ 7 import requests 8 from bs4 import BeautifulSoup 9 import re 10 #import traceback 11 12 def getHTMLText(url,code='utf-8'):#参数code缺省值为‘utf-8’(编码方式) 13 try: 14 r=requests.get(url,timeout=30) 15 r.raise_for_status() 16 #r.encoding=r.apparent_encoding 17 r.encoding=code 18 return r.text 19 except: 20 return '' 21 22 def getStockList(lst,stockURL): 23 html=getHTMLText(stockURL,'GB2312') 24 soup=BeautifulSoup(html,'html.parser') 25 a=soup.find_all('a') 26 for i in a: 27 try: 28 href=i.attrs['href'] 29 lst.append(re.findall(r'[s][hz]d{6}',href)[0]) 30 except: 31 continue 32 33 def getStockInfo(lst,stockURL,fpath): 34 count=0# 35 for stock in lst: 36 url=stockURL+stock+'.html' 37 html=getHTMLText(url) 38 try: 39 if html=='': 40 continue 41 infoDict={} 42 soup=BeautifulSoup(html,'html.parser') 43 stockInfo=soup.find('div',attrs={'class':'stock-bets'}) 44 45 name=stockInfo.find_all(attrs={'class':'bets-name'})[0] 46 infoDict.update({'股票名称':name.text.split()[0]})#用空格分开,得到股票名称 47 48 keyList=stockInfo.find_all('dt') 49 valueList=stockInfo.find_all('dd') 50 for i in range(len(keyList)): 51 key=keyList[i].text 52 val=valueList[i].text 53 infoDict[key]=val 54 55 with open(fpath,'a',encoding='UTF-8') as f: 56 f.write(str(infoDict)+'n') 57 count=count+1# 58 print('r当前进度:{:.2f}%'.format(count*100/len(lst)),end='')#动态显示进度,‘r’实现光标移动,即为不换行的效果 59 except: 60 count=count+1 61 print('r当前进度:{:.2f}%'.format(count*100/len(lst)),end='')#动态显示进度,‘r’实现光标移动,即为不换行的效果 62 #traceback.print_exc() 63 continue 64 65 66 def main(): 67 stock_list_url='http://quote.eastmoney.com/stocklist.html' 68 stock_info_url='https://gupiao.baidu.com/stock/' 69 output_file='C:/Users/DONG LONG RUI/.spyder-py3/BaiduStockInfo.txt' 70 slist=[] 71 getStockList(slist,stock_list_url) 72 getStockInfo(slist,stock_info_url,output_file) 73 74 main()
由于requests库爬虫的限制,我运行后速度会比较慢,后续可尝试scrapy爬虫。
又想到bs4中的BeautifulSoup和re库都可用于搜索html中的目标信息,但两者一般结合起来使用:
先用BeautifulSoup找到目标信息所在的特定标签,然后在这些标签内容中使用正则表达式去匹配。
写作背景:作为一名金融从业者,在个人的业务投资上,经常会需要通过数据分析,加上金融逻辑的推演决定自己的投资策略。提到数据分析,就必然会提到数据采集。作为个人投资者,数据信息最多的就是来自互联网。如何高效获取自己需要的数据并加以分析,就是在下开始学习爬虫的原因。通过记录学习情况,梳理自己的知识框架,同时也能分享给大家,找到一起努力奋斗的小伙伴。
个人背景:理工科类大学毕业,从事银行、保险等金融相关工作近10年。
编程能力:大学期间学过C语言和SQL语言,但是10年来几乎很少应用,忘得差不多。
学习Python的原因:网上关于Python的爬虫案例较多,据说Python语言相比C和JAVA更近自然语言。
学习时长:工作之后的业余时间,累计近一个月。
学习成果:掌握简单的爬虫技术。
系统环境:windows 10
IDE:Pycharm
Python版本:Python2.7 (Ananconda)
知识点:1、涉及到的库urllib,urllib2,re,beautifulsoup,lxml,gzip,StringIO,csv,mysql
2、掌握用urllib,urllib2获取网页
1)最简单的获取方式urllib2.urlopen()
2)加入报头headers
3)加入代理proxy
4)加入cookies
5)定制自己的opener
6)网页乱码的处理:chardet、decode()、gzip、StringIO库
3、通过网页解析,获得需要的数据
1)学会用正则表达式解析
2)学会用BeautifulSoup解析网页
3)学会用lxml xpath解析网页
4、数据的读写
1)txt文件的读写
2)CSV文件的读写
3)MySQL的读写
更多的内容学习 点我
本文适用人群:零基础学爬虫、小白学爬虫、简单爬虫的学习框架
其他:1)本文通过爬虫案例学习以上学习以上知识点。并尽可能对每一段代码做注解,
注解开头为#。
2)本文不会涉及到class类和函数的概念,便于初学者学习基本知识。
3)本文仅作为知识学习的笔记与分享,请勿在未经作者的同意下商用,更希望每一个编程爱好者以ipipgo的心态学习,不要用于违法乱纪。
参考网站:1)廖雪峰的Python 2.7教程:学习所有Python的最基础语法,当词典用。
2)简明 Python 教程,当词典用
3)崔庆才的个人博客,Python爬虫学习系列教程 | 静觅,相当多的实例教程,唯一 缺点就是很多文章是半年前到1年前写的,很多网页都纷纷改版,直接运行里 面的代码无法爬取,但是可以作为爬虫思路的指引。
爬取对象:上海房产网_上海二手房_上海新房_上海租房-上海链家网
感谢链家网,提供了很好的学习土壤。
我是分割线————————————————————————————————————
正文与代码:
# encoding: utf-8
#该行注释是为了解决python中文的乱码问题,所有中文以utf-8格式解析,也可以写成 # -*- coding: utf-8 -*-
1、添加需要用到的库urllib,urllib2,re,beautifulsoup,lxml,csv,mysql,gzip,StringIO
import urllib #网页解析库 import urllib2 #网页解析库 import re # 正则表达式的库 import cookielib #cookie的库 from bs4 import BeautifulSoup # BeautifulSoup的库 import lxml.html # lxml xpath的库 from lxml import etree # lxml xpath的库 import csv #csv的库 from mysql import connector # 连接MySQL的库
库的安装命令,cmd下执行:pip install urllib
pip install urllib==1.0.0 #制定版本的库安装
pip install –upgrade urllib #库的升级
其他pip命令可以参考:pip安装使用详解 – 爱开源
2、掌握用urllib,urllib2获取网页
1)最简单的形式:
url = 'http://sh.lianjia.com/ershoufang/d1' response = urllib2.urlopen(url) content = response.read() print content
输出结果:
说明爬取成功,看来链家非常的友好,并没有设立针对urlopen显性的反爬虫机制。
怎么判断爬取是否成功
print content.getcode()
如果返回值是200则爬取成功,如果是301、302则是重定位,如果是404则是表示页面不存在
详细可以参考 301、404、200、304等HTTP状态 – Lynn.Zhou的专栏 – 博客频道 – CSDN.NET
2)加入报头headers,如果遇到有显性反爬虫机制的情况,返回一般就不是200了,这个时候怎么办?就给爬虫带个帽子,假装自己不是爬虫。
headers = { 'User – Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36' }
报头一般用浏览器按F12,查看Network选项卡里都能看到,实在不行,你可以把整个Request Headers里的内容,以字典的方式扔进去。
3)尝试加入代理IP机制,现在越来越多的网站 没有显性的反爬虫模式,而是采用隐性的反爬虫机制,比如你开始爬取第一页的时候没问题,但是爬着爬着就把你BAN了,而一般BAN的是你的IP地址,所以在做大量数据爬取的时候建议加入IP代理机制。
代理IP地址怎么获取,请自行百度或者谷歌。
proxy_handler = urllib2.ProxyHandler({"http": '101.231.67.202:808'}) opener = urllib2.build_opener(proxy_handler,urllib2.HTTPHandler)
4)加入cookies
cookie = cookielib.LWPCookieJar() cookie_handler = urllib2.HTTPCookieProcessor(cookie) opener = urllib2.build_opener(cookie_handler,urllib2.HTTPHandler)
5)定制自己的opener
#同时加入proxy和cookie opener = urllib2.build_opener(proxy_handler,cookie_handler,urllib2.HTTPHandler)
6)网页乱码的处理:chardet、decode()、gzip、StringIO 乱码表现一:chardet、decode()
有时解析网页会发现大量的奇怪符号,嗯,这就是乱码。乱码的一般都是中文。
访问的网站是搜狐,同样调取查看器。
在<head>里有以下内容:
<meta http-equiv=”content-type” content=”text/html; charset=GBK”>
说明网站的中文是用GBK的。
print content.read().decode('gbk')
decode的其他形式:decode(‘utf-8′,’ignore’) #忽略不能解码的内容,确保命令正常运行
用chardet的库来解析网络的代码
import chardet url = 'http://www.sohu.com' response = urllib2.urlopen(url) content = response.read() charset_info = chardet.detect(content) print charset_info
乱码表现二:调用gzip、StringIO库
所有的内容都乱码了。。。。
<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″>
明明是gb2312,用decode(‘gbk’,’ignore’)居然不能解码。。。
乱码的网页报头
普通网页的报头
关键在于RESPONSE里是否有 Vary:Accept-Encoding。如果没有申明,网页要自行解压。
gzip和StringIO派上用处了:
import gzip import StringIO url = 'http://land.fang.com' response = urllib2.urlopen(url) content = response.read() content = StringIO.StringIO(content) gzipper = gzip.GzipFile(fileobj=content) content = gzipper.read().decode('gbk')
3、通过网页解析,获得需要的数据
还是以上海二手房|上海二手房出售|最新上海二手房信息 – 上海链家网为案例
获取所有行政区的链接和名字
1)学会用正则表达式解析
pattern_district = re.compile('<a href="/ershoufang.*?class="" >(.*?)</a>', re.S) districts = re.findall(pattern_district, content) for district in districts: print district
熟练掌握.*?和(.*?)的贪婪匹配技巧,一般都能轻松获取
但是如果要获取行政区的链接就很痛苦了,因为正则表达式只能找规律,周围匹配的字段越特殊,那么越容易找到。
pattern_district = re.compile('<a href="(.*?)" gahref=".*? class="" >(.*?)</a>', re.S) districts = re.findall(pattern_district, content) for district in districts: print district
这样写的结果,会匹配到很多不想管的内容
打包一起找再处理
pattern_district = re.compile('<a href="/ershoufang/".*?</a>.*?<div class="item-list">(.*?)</div>',re.S) districts = re.findall(pattern_district, content) districts =districts[0] print districts
再一次正则匹配:
pattern = re.compile('<a href="(.*?)" gahref.*?>(.*?)</a>',re.S) item = re.findall(pattern,districts) for i in item: print i[0], i[1]
神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试