【第三周】网络爬虫之实战

一、Re(正则表达式)库入门

1.正则表达式的概念

1.1正则表达式是什么

正则表达式是用来简洁表达一组字符串的表达式。
使用正则表达式的优势就是:简洁、一行胜千言 一行就是特征(模式)

例1:代表一组字符串:

例2:代表一组(无穷个)字符串:

例3:代表一组具有某种特点但是枚举起来很繁琐的字符串:

简单来说:
正则表达式是用来简洁表达一组字符串的表达式
正则表达式是一种通用的字符串表达框架
正则表达式是一种针对字符串表达“简洁” 和“ 特征” 思想的工具
正则表达式可以用来判断某字符串的特征归属

1.2正则表达式可以干嘛

正则表达式在文本处理中十分常用:
可用来表达文本类型的特征(病毒、入侵等)
可用来同时查找或替换一组字符串
可用来匹配字符串的全部或部分
可用来……
最主要应用在字符串匹配

1.3如何(在python)使用正则表达式

使用re模块:

2.正则表达式的语法

从下面一个经典例子讲起:

可以看出:正则表达式语法由字符操作符构成

2.1正则表达式的常用操作符


2.2正则表达式语法实例

2.3经典正则表达式实例

2.3.1匹配IP地址的正则表达式

3.Re库的基本使用

Re库是Python的标准库,主要用于字符串匹配
调用方式:import re

3.1正则表达式的表示类型

包含2种:raw string类型(原生字符串类型)和string类型

re库采用raw string类型表示正则表达式,表示为: r’text’
例如:

r'[1‐9]\d{5}'
r'\d{3}‐\d{8}|\d{4}‐\d{7}'

简单来说:raw string是不包含对转义符再次转义的字符串。

re库也可以采用string类型表示正则表达式,但更繁琐
例如:

'[1‐9]\\d{5}'
'\\d{3}‐\\d{8}|\\d{4}‐\\d{7}'

建议:当正则表达式包含转义符时,使用raw string。而为了使用的方便,笔者还是建议同一用raw string。

关于所有的转义字符和所对应的意义,可看这里:

3.2Re库的主要功能函数

总体介绍:

3.2.1 re.search()

函数原型:re.search(pattern, string, flags=0)
pattern : 正则表达式的字符串或原生字符串表示
string : 待匹配字符串
flags : 正则表达式使用时的控制标记,常用标记如下:

功能:在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象

举例:

3.2.2 re.match()

函数原型:re.match(pattern, string, flags=0),参数同上
pattern : 正则表达式的字符串或原生字符串表示
string : 待匹配字符串
flags : 正则表达式使用时的控制标记

功能:从一个字符串的开始位置起匹配正则表达式,返回match对象

举例:

【重要】这里需要注意的是:当match为None时,直接输出match.group(0)就会报错。所以,为了程序的稳定性,通常需要使用:

if match:match.group(0)

来避免该错误。这种处理方法在爬虫程序中经常会见到。

3.2.3 re.findall()

函数原型:re.findall(pattern, string, flags=0),参数同上
pattern : 正则表达式的字符串或原生字符串表示
string : 待匹配字符串
flags : 正则表达式使用时的控制标记

功能:搜索字符串,以列表类型返回全部能匹配的子串

举例:

3.2.4 re.split()

函数原型:re.split(pattern, string, maxsplit=0, flags=0)
pattern : 正则表达式的字符串或原生字符串表示
string : 待匹配字符串
maxsplit: 最大分割数,剩余部分作为最后一个元素输出
flags : 正则表达式使用时的控制标记

功能:将一个字符串按照正则表达式匹配结果进行分割返回列表类型

举例:

3.2.5 re.finditer()

函数原型:re.finditer(pattern, string, flags=0)
pattern : 正则表达式的字符串或原生字符串表示
string : 待匹配字符串
flags : 正则表达式使用时的控制标记
功能:搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象

举例:

3.2.6 re.sub()

函数原型:re.sub(pattern, repl, string, count=0, flags=0)
pattern : 正则表达式的字符串或原生字符串表示
repl : 替换匹配字符串的字符串
string : 待匹配字符串
count : 匹配的最大替换次数
flags : 正则表达式使用时的控制标记
功能:在一个字符串中替换所有匹配正则表达式的子串返回替换后的字符串

举例:

3.3Re库的另一种等价用法

举例:

re.compile函数原型:regex = re.compile(pattern, flags=0)
pattern : 正则表达式的字符串或原生字符串表示
flags : 正则表达式使用时的控制标记

功能:将正则表达式的字符串形式编译成正则表达式对象

那么,Re库的函数用法等价为:

4.Re库的Match对象

Match对象是一次匹配的结果,包含匹配的很多信息

属性有:

方法有:

实例:

5.Re库的贪婪匹配和最小匹配

5.1贪婪匹配

首先看一个例子:

>>> match = re.search(r'PY.*N', 'PYANBNCNDN')
>>> match.group(0)

可以发现代码中的正则表达式r’PY.*N’可同时匹配长短不同的多项,那么该返回哪一个呢?
实际输出结果为:

'PYANBNCNDN'

原因是:Re库默认采用贪婪匹配,即输出匹配最长的子串

5.2最小匹配

那么该如何如何输出最短的子串呢?
解决方法:修改r'PY.*N'r'PY.*?N'即可:

>>> match = re.search(r'PY.*?N', 'PYANBNCNDN')
>>> match.group(0)
'PYAN'

5.2.1最小匹配操作符

只要长度输出可能不同的,都可以通过在操作符后增加?变成最小匹配:

6.单元小结

二、实例1-淘宝商品比价定向爬虫

1.功能描述

目标:获取淘宝搜索页面的信息,提取其中的商品(书包)名称和价格
具体实现需要解决的问题
1.淘宝的搜索接口:

https://s.taobao.com/search?q=keyword

第一个页面的链接为:

https://s.taobao.com/search?q=书包&js=1&stats_click=search_radio_all%
3A1&initiative_id=staobaoz_20170105&ie=utf8

2.翻页的处理:
打开网页后,发现数据是分布在多个页面上的:

一般来说,这多个页面的链接是有一定的规律性的:

可以看到,修改s这个属性值就可以得到后面的页面的URL链接了。

3.技术路线:requests‐bs4‐re

4.观察网页源代码,找到要爬取的数据(书包的价格和名称)的所在位置:

2.程序结构设计

步骤1:提交商品搜索请求,循环获取页面
步骤2:对于每个页面,提取商品名称和价格信息
步骤3:将信息输出到屏幕上

首先,写出总体较抽象的代码:

总体代码:

#CrowTaobaoPrice.py
import requests
import redef getHTMLText(url):try:r = requests.get(url, timeout=30)r.raise_for_status()r.encoding = r.apparent_encodingreturn r.textexcept:return "failed\n"def parsePage(ilt, html):try:plt = re.findall(r'\"view_price\"\:\"[\d\.]*\"',html)tlt = re.findall(r'\"raw_title\"\:\".*?\"',html)for i in range(len(plt)):price = eval(plt[i].split(':')[1])#eval函数将字符串转为数字title = eval(tlt[i].split(':')[1])ilt.append([price , title])except:print("")def printGoodsList(ilt):tplt = "{:4}\t{:8}\t{:16}"print(tplt.format("序号", "价格", "商品名称"))count = 0for g in ilt:count = count + 1print(tplt.format(count, g[0], g[1]))def main():goods = '书包'depth = 3 #改段代码是演示用的,depth不能太大,淘宝本是不允许爬取搜索页面的start_url = 'https://s.taobao.com/search?q=' + goodsinfoList = []for i in range(depth):try:url = start_url + '&s=' + str(44*i)html = getHTMLText(url)parsePage(infoList, html)except:continueprintGoodsList(infoList)main()

输出结果:

序号    价格            商品名称1    129.00          瑞士军刀旅行双肩包男中学生书包电脑背包2    69.00           迪士尼书包小学生男女1-3-4-6年级米奇减负背包儿童书包8-10-12岁3    78.00           泰格奴防盗商务男女双肩包男士背包休闲学生书包电脑包韩版旅行包4    143.00          七匹狼男士背包 书包中学生男商务双肩电脑包旅行包 背包双肩包男5    79.00           日韩大容量帆布双肩包男潮双肩背包旅行包英伦风书包中学生女6    167.00          越古帆布双肩包女士休闲复古文艺运动背包韩版中学生书包男包女包7    37.44           日韩简约清新帆布双肩包女韩版潮学院风校园学生背包大小款书包女8    69.00           2016新款韩版潮真皮背包时尚女士双肩包女百搭简约大容量学生书包9    44.55           包包2017新款pu卡通小猫双肩包女韩版时尚百搭学院风学生书包背包10    55.00           双肩包女士包包2017新款学生背包时尚韩版妈咪女包休闲书包旅行包11    49.90           双肩包女士背包2017春季新款女包时尚百搭书包韩版休闲旅行包女潮12    79.20           幼儿园布朗熊书包3-4-5岁 背包双肩包 手提包韩国热款 轻便容量大13    59.00           2016新款个性创意磨砂皮海豚书包女双肩包男大容量旅行背包电脑包14    198.00          SALONBUS沙隆巴斯 定制款复古英伦老花迷你小书包双肩背包斜挎包15    145.00          双肩包男士背包旅游韩版学生书包时尚潮流休闲旅行潮包皮质电脑包16    97.51           超值卡拉羊韩版学院风女双肩包大学生初中生中学生书包女旅行电脑17    159.00          SHEVAN/希梵2016新款时尚女包双肩包女韩版百搭休闲背包简约书包18    12.50           韩国版文艺2017简约帆布包男女单肩手提购物袋大女包学生书包森潮19    99.36           米菲包包女小清新双肩包女学院风中学生书包帆布旅行背包大容量20    98.00           2017女包上新款韩版潮双肩包女牛津布小怪兽背包时尚学院风书包21    111.72          2017新款英伦时尚简约双肩包女包韩版潮流大背包学院风学生书包包22    22.98           包邮秋冬文艺纯色布贴灯芯绒布包单肩斜跨两用拉链包女书包9色入23    139.00          安踏配件双肩背包男女通用 春秋季笔记本电脑包学生书包背包24    58.65           韩版多功能单肩双肩两用妈咪包大容量背包牛津布配真皮斜挎大书包25    73.50           马塞洛双肩包男士韩版商务背包女中学生书包双肩休闲电脑包旅行包26    59.00           乐天双肩包日系校园森女系撞色拼接大容量书包男女情侣背包电脑包27    99.00           安踏男女双肩背包学生书包2016冬季新款时尚百搭旅游背包1964816628    79.00           费莱德简约男包韩版学生书包女包潮PU皮男士双肩背包休闲旅行包29    108.00          熊本熊包包学生包jk制服包女单肩书包可爱日系手提包通勤学院风萌30    75.00           勇士库里30号 汤普森 大容量双肩包篮球背包 男 女包 学生书包nba31    98.58           牛津布双肩包女日韩版时尚防水帆布背包韩国校园大学生休闲书包男32    47.90           双肩包女韩版潮青少年休闲可爱背包百搭简约旅游灰粉色学生书包女33    76.00           伊布雅双肩包女日韩版男背包纯色百搭中学生书包休闲电脑包旅行包34    19.90           2016韩版亲子包儿童双肩背包胸包宝宝男童女童米奇皮包书包潮包35    58.00           2016新款欧美双肩包女韩版可爱卡通创意个性喷绘背包中学生书包男36    125.00          七匹狼新款双肩包韩版男女休闲背包学生书包商务电脑包旅行包正品37    39.90           彩带流苏双肩包女2016新款铆钉徽章迷你小背包学院风休闲单肩书包38    89.76           2017新款尼龙牛津布双肩包女包韩版潮轻休闲背包学生书包妈咪大包39    77.52           2016新款春铆钉双肩包女韩版pu学院风2017小熊背包休闲百搭书包潮40    49.90           2016新款韩版双肩包女复古PU背包潮百搭学院风旅行休闲中学生书包41    59.00           秀洛我的世界Minecraft苦力怕书包游戏周边双肩背包男女学生夜光42    79.00           森马双肩包女韩版 2016新款简约百搭学院风大学生书包男电脑包潮43    59.00           2017新款牛津布双肩包女夏尼龙布防水书包女士休闲旅行背包韩版潮44    38.00           瑞士军刀SWISSWIN儿童书包小孩双肩包卡通背包SWK1001A/B/C/D/E/F45    59.90           包包女2017新款潮韩版百搭学院铆钉背包简约PU书包韩版双肩包小包46    69.00           百搭明星新款双肩包软皮女包韩版学院风休闲时尚书包旅行背包潮女47    146.51          JanSport杰斯伯超级叛逆儿童款迷你双肩包书包TDH6系列48    59.00           背包双肩包男韩版大学生高中学生开学书包时尚潮流旅行旅游包简约49    69.00           双肩包女韩版潮书包2017新款时尚百搭软羊皮女士包包旅行真皮背包50    258.00          NIKE双肩包KYRIE 欧文男子篮球运动装备背包书包BA5133 BA525951    179.00          匡威包双肩包男包女包2017图案学生书包运动帆布背包10004349-A0152    119.00          【买一送一】森马双肩包女韩版 百搭学院风大学生书包男旅行包潮53    248.00          anello双肩包日本代购正品乐天男女书包包两用背包简约书包防水包54    39.90           2016秋冬新款尼龙双肩包女背包牛津布包女士韩版潮书包女包方扣55    158.00          开学季包邮订制图案炫彩硬壳电脑包18寸中学生高中生书包56    28.50           韩国软妹灯芯绒双肩包原宿复古百搭学院风帆布日系男女学生书包潮57    116.82          韩国复古个性书包女双肩包防泼水大学韩版学院风bf布料女小清新男58    109.00          日本代购乐天双肩包磨砂手提包大容量电脑背包妈咪学生书包旅游包59    30.24           新款时尚休闲防泼水书包女中学生旅行双肩包 学院风潮流印花背包60    218.00          GOLF新品男士双肩包时尚多色旅行背包大学生书包电脑包悠闲包包61    47.36           双肩包女韩版2017新款潮百搭休闲皮质大学生书包简约气质女生背包62    277.00          正品匡威休闲双肩包男女学生书包旅行包 10002205102 1000220500163    99.00           2017新款鲨鱼大小背包牛津布双肩包女学生男女书包旅行包64    165.00          2016正品阿迪达斯男女包学生书包双肩背包AY4200 4183 4184 419965    79.00           冰雪奇缘儿童书包可爱双肩包女童8-10-12岁小学生书包3-4-6年级66    37.00           猫猫包袋2017女包上新多用双肩包休闲拼色单肩斜挎包包女日韩书包67    58.00           书包男女学生阴阳师动漫游戏周边神乐安培晴明莹草大天狗双肩背包68    29.90           韩国ulzzang日本原宿软妹美少女战士露娜猫咪卖萌小号双肩背书包69    49.90           小学生书包1-2-3年级4男孩双肩背包女儿童 6-7-8-9岁休闲旅行防水70    22.90           韩国经典百搭黑色刺绣双肩包月亮十字架学生背包大容量情侣书包女71    45.22           2017新款磨砂流苏双肩包女韩版大容量学院风背包百搭休闲学生书包72    69.00           小恶魔小怪兽潮牌双肩包韩版男女初高中学生情侣书包夜光帆布包73    49.90           户外登山包大容量书包潮女韩版多功能旅行背包运动双肩包男行李包74    88.00           女双肩包复古欧美学生书包休闲背包电脑包碎花75    39.90           双肩包女韩版pu背包时尚百搭女包学院风抽绳包包2016新款潮书包女76    118.00          韩国kk树书包小学生男6-12周岁儿童书包女童1-3-5年级护脊双肩包77    79.00           卡拉羊儿童小背包宝宝幼儿园书包男女小双肩包可爱卡通小包C600578    139.00          轻便防水中号背包双肩包多袋多功能多花色 书包79    59.40           双肩包男个性学生书包时尚潮流简约旅行背包皮商务休闲防水电脑包80    59.00           休闲双肩包女士背包学院风韩版学生书包时尚潮复古旅行电脑包潮包81    65.00           牛津布全防水包包女生书包韩版学院风背包简约百搭学生双肩包帆布82    45.00           李小璐同款双肩包女旅行包2016春夏款亮片背包女包韩版潮亮片书包83    68.16           双肩包女包韩版PU皮全防水大容量高中学生书包流苏背包校园学院风84    179.00          瑞戈瑞士军刀男女背包双肩包旅行包中学生书包休闲商务时尚包85    59.00           休闲双肩包男士背包青年PU皮韩版潮流学生书包时尚大旅行包电脑包86    19.80           韩版背包折叠轻便防水女旅行男旅游户外双肩包简约百搭学院风书包87    99.00           奥王双肩包背包男初中生学生书包休闲男士商务旅行大容量电脑包88    23.00           2016新款双肩包背包韩版时尚女包大容量女士包包简约双肩学生书包89    79.00           黛妃洛 秋冬新品编织双肩包女士包时尚潮背包旅行大容量女包书包90    41.80           韩版简约时尚休闲镭射pu双肩背包女中学生校园书包大容量百搭纯色91    168.00          左岸潇明星同款潮牌双肩包菱格子品牌书包学生超轻便尼龙旅行背包92    59.00           阪元宿宿大容量印花防水双肩包女韩版潮休闲背包中学生书包旅行包93    99.00           瑞士军刀正品双肩包男商务15.6寸电脑包17寸中学生书包大容量背包94    369.00          艾力夫|NEW BALANCE GC721032 GC641013 男女包运动包书包双肩包95    49.90           新款双肩包女韩版pu皮森女系学院风学生书包小清新休闲百搭背包潮96    49.00           双肩包女韩版学院风定型猫耳朵防水双肩大高中学生男书包百搭背包97    49.00           【天天特价】户外登山包大容量旅行旅游背包双肩包男女运动包书包98    137.70          JTXS正版镶钻亮片双肩背包女韩版明星同款亮片双肩背潮流旅游书包99    136.08          ONLY双肩包女包2017新款韩版个性铆钉背包时尚书包潮流包包108100    74.75           2017新款休闲旅行软皮配牛皮背包双肩包韩版潮女包学院风学生书包101    1568.00         美国正品新款MK双肩包RHEA ZIP铆钉书包旅行背包真皮中号小号男女102    872.00          美国代购蔻驰COACH新款迷你双肩小书包女背包F38395 38302 38263103    35.00           单肩斜挎包加厚休闲布包大书包旅行包防水尼龙女包袋104    27.90           儿童背包韩版中大童布小学生书包男孩时尚休闲旅行男童双肩包潮包105    13.90           韩版冬季新款背包女包学生双肩包旅行包中小学书包大容量学生双背106    48.00           女包双肩包pu复古子母包多功能背包日韩风旅行潮包学院风学生书包107    79.00           双肩包男帆布旅行背包韩版百搭高中大学生书包女时尚潮流个性街头108    88.00           双肩包男定制 电脑包背包 学生书包旅行背包定做logo109    59.00           特价软皮双肩包女韩版背包简约包包学院风皮质女生书包休闲旅行包110    88.00           Carney Road卡尼路军双肩包电脑包韩版潮运动旅行包高中学生书包111    69.99           13寸手提电脑包男女军迷战术双肩包防水迷彩背包旅行单肩斜挎书包112    45.00           死神 书包 双肩包 周边 背包 包包 动漫 黑崎一护 BLEACH 冬狮郎113    39.00           黑白条纹双肩包背包女撞色学生书包帆布旅行包回家包日韩版情侣包114    45.00           2016新款潮时尚小香风女包尼龙牛津布包双肩书包单肩斜挎旅行背包115    55.00           牛津布双肩包男生韩版帆布背包时尚书包学院风旅行包新款潮书包包116    35.00           Aape 猿人头 韩版英伦拼色学院风帆布双肩包男人书包背包时尚潮流117    39.60           双肩包女包韩版皮料书包时尚百搭单肩包女士包包2017新款潮后背包118    99.00           欧美复古双肩包女生学院风背包PU皮大容量书包潮高中 大学生书包119    39.48           韩版双肩包男女简约休闲初中小学生书包帆布潮学院风旅行电脑背包120    39.90           韩国代购水桶双肩包女韩版潮纯色防水背包学生书包大容量旅行包121    449.00          代购直邮16新款欧美休闲百搭guess柳钉双肩包女包书包包邮122    69.00           安踏书包背包春季皮革双肩背包休闲日韩学院双肩包19618158123    99.00           安踏双肩背包学生书包2016夏季新款户外运动旅行电脑包|19628159124    48.00           邮暴走大事件书包王尼玛暴走漫画个性搞笑男女背包双肩包原宿星空

三、实例2-股票数据定向爬虫

1.功能描述

目标:获取上交所和深交所所有股票的名称和交易信息
输出:保存到文件中
技术路线:requests‐bs4‐re

2.数据网站的选择

候选数据网站:
新浪股票:http://finance.sina.com.cn/stock/
百度股票:https://gupiao.baidu.com/stock/
东方财富网:http://quote.eastmoney.com/stocklist.html

选择方法:
选取原则:股票信息静态存在于HTML页面中,非js代码生成,没有Robots协议限制
选取方法:浏览器 F12,源代码查看等
选取心态:不要纠结于某个网站,多找信息源尝试

测试结果:
由于东方财富网有所有股票的列表,所有股票的名称和代号都可以在一个页面上找到:

查看源代码后,可以看到股票名称和代号是有规律的。

然而点进去某个具体页面后发现数据采取不方便,页面比较繁杂。

测试百度股票后,发现可以直接通过股票代号来直接查询得到股票具体信息:

例如查询启明星辰这支股票:

我们需要抓取的数据就是上面这些。查看源代码后可以发现数据是静态存在于HTML页面中的。

确定结果:
获取股票列表:
东方财富网:http://quote.eastmoney.com/stocklist.html
获取个股信息:
百度股票:https://gupiao.baidu.com/stock/
(例子:单个股票:https://gupiao.baidu.com/stock/sz002439.html)

3.程序的结构设计

步骤1:从东方财富网获取股票列表
步骤2:根据股票列表逐个到百度股票获取个股信息
步骤3:将结果存储到文件

首先,编写较为抽象的代码:

getStockList函数的实现:
上面提到,股票的代号信息是在网页源代码的a标签的href属性值上的,因此可通过正则表达式来提取。这里选择正则表达式为:r"[s][hz]\d{6}"(之所以不是r"[s][h]\d{6}"的原因见下面第二周图片)。

将网页向下滑动一段时间后,发现href属性值的代码起那么的两个字母sh改成了sz了。(实际上两者分别是上海和深圳的简写)。

代码:

def getStockList(stockList, stockURL):html = getHTMLText(stockURL)soup = BeautifulSoup(html, 'html.parser') #股票名称和代号在网页源代码的a标签的href属性上a = soup.find_all('a')for i in a:try:href = i.attrs['href']stockList.append(re.findall(r"[s][hz]\d{6}", href)[0])except:continue

getStockInfot函数的实现:
由下面看到的源代码中:

可见数据是在<div class="bets-content">...</div>这个div标签内。
而下面这张图片的数据则是保存在上面的源代码的dt和dd标签上。

代码:

def getStockInfo(stockList, stockURL, fpath):for stock in stockList:url = stockURL + stock + ".html" #个股的详细查询页面html = getHTMLText(url)try:if html == "":#异常判断continueinfoDict = {}soup = BeautifulSoup(html, 'html.parser')#找到第一个class属性值为stock-bets的div标签stockInfo = soup.find('div', attrs={'class': 'stock-bets'})if stockInfo==None:#异常判断continue#找到第一个class属性值为bets-name的a标签name = stockInfo.find('a',attrs={'class': 'bets-name'})#得到股票名称infoDict.update({'股票名称': name.text.split()[0]})#通过阅读网页源代码,发现数据可用键值对的形式存储#找到所有dt标签(数据键值对的键)keyList = stockInfo.find_all('dt')#找到所有dd标签(数据键值对的值)valueList = stockInfo.find_all('dd')for i in range(len(keyList)):key = keyList[i].textval = valueList[i].textinfoDict[key] = val#将新增数据添加到文件with open(fpath, 'a', encoding='utf-8') as f:f.write(str(infoDict))except:#打印异常信息,这样的做法是 即是出现了异常,异常信息可以显示出来,但是程序仍会接着进行traceback.print_exc()continue

总体代码:

# CrawBaiduStocksA.py
import requests
from bs4 import BeautifulSoup
import traceback
import redef getHTMLText(url):try:r = requests.get(url)r.raise_for_status()r.encoding = r.apparent_encodingreturn r.textexcept:return ""def getStockList(lst, stockURL):html = getHTMLText(stockURL)# 股票名称和代号在网页源代码的a标签的href属性上soup = BeautifulSoup(html, 'html.parser')a = soup.find_all('a')for i in a:try:href = i.attrs['href']lst.append(re.findall(r"[s][hz]\d{6}", href)[0])except:continuedef getStockInfo(stockList, stockURL, fpath):for stock in stockList:url = stockURL + stock + ".html" #个股的详细查询页面html = getHTMLText(url)try:if html == "":#异常判断continueinfoDict = {}soup = BeautifulSoup(html, 'html.parser')#找到第一个class属性值为stock-bets的div标签stockInfo = soup.find('div', attrs={'class': 'stock-bets'})if stockInfo==None:#异常判断continue#找到第一个class属性值为bets-name的a标签name = stockInfo.find('a',attrs={'class': 'bets-name'})#得到股票名称infoDict.update({'股票名称': name.text.split()[0]})#通过阅读网页源代码,发现数据可用键值对的形式存储#找到所有dt标签(数据键值对的键)keyList = stockInfo.find_all('dt')#找到所有dd标签(数据键值对的值)valueList = stockInfo.find_all('dd')for i in range(len(keyList)):key = keyList[i].textval = valueList[i].textinfoDict[key] = val#将新增数据添加到文件with open(fpath, 'a', encoding='utf-8') as f:f.write(str(infoDict))except:#打印异常信息,这样的做法是 即是出现了异常,异常信息可以显示出来,但是程序仍会接着进行traceback.print_exc()continuedef main():# 股票列表页面(可得到所有股票代号和名称)stock_list_url = 'http://quote.eastmoney.com/stocklist.html'# 个股详细查询页面(根据股票代号可查询)stock_info_url = 'https://gupiao.baidu.com/stock/'# 保存爬取数据的文件output_file = 'BaiduStockInfo.txt'# 股票列表stockList = []# 得到股票列表getStockList(stockList, stock_list_url)# 得到所有个股的详细信息,并保存在输出文件getStockInfo(stockList, stock_info_url, output_file)main()

4.实例优化

优化目的:提高用户体验

4.1getHTMLText函数的编码识别的优化

def getHTMLText(url):try:r = requests.get(url)r.raise_for_status()r.encoding = r.apparent_encodingreturn r.textexcept:return ""

getHTMLText函数中的r.apparent_encoding需要分析文本,运行较慢,可辅助人工分析。
修改为:

def getHTMLText(url, code="utf-8"):try:r = requests.get(url)r.raise_for_status()r.encoding = codereturn r.textexcept:return ""

并修改getStockList中调用getHTMLText的部分代码,修改后如下:

def getStockList(lst, stockURL):html = getHTMLText(stockURL, "GB2312")soup = BeautifulSoup(html, 'html.parser') a = soup.find_all('a')for i in a:try:href = i.attrs['href']lst.append(re.findall(r"[s][hz]\d{6}", href)[0])except:continue

4.2提高用户体验:增加动态进度条的显示

在getStockInfo函数添加如下代码:

```python
def getStockList(lst, stockURL):count=0#.....with open(fpath, 'a', encoding='utf-8') as f:f.write( str(infoDict) + '\n' )count = count + 1print("\r当前进度: {:.2f}%".format(count*100/len(lst)),end="")except:count = count + 1print("\r当前进度: {:.2f}%".format(count*100/len(lst)),end="")continue

4.3优化后的总体代码:

# CrawBaiduStocksB.py
import requests
from bs4 import BeautifulSoup
import traceback
import redef getHTMLText(url, code="utf-8"):try:r = requests.get(url)r.raise_for_status()r.encoding = codereturn r.textexcept:return ""def getStockList(lst, stockURL):html = getHTMLText(stockURL, "GB2312")# 股票名称和代号在网页源代码的a标签的href属性上soup = BeautifulSoup(html, 'html.parser')a = soup.find_all('a')for i in a:try:href = i.attrs['href']lst.append(re.findall(r"[s][hz]\d{6}", href)[0])except:continuedef getStockInfo(stockList, stockURL, fpath):count=0 #用于进度条的计数器for stock in stockList:url = stockURL + stock + ".html" #个股的详细查询页面html = getHTMLText(url)try:if html == "":#异常判断continueinfoDict = {}soup = BeautifulSoup(html, 'html.parser')#找到第一个class属性值为stock-bets的div标签stockInfo = soup.find('div', attrs={'class': 'stock-bets'})if stockInfo==None:#异常判断continue#找到第一个class属性值为bets-name的a标签name = stockInfo.find('a',attrs={'class': 'bets-name'})#得到股票名称infoDict.update({'股票名称': name.text.split()[0]})#通过阅读网页源代码,发现数据可用键值对的形式存储#找到所有dt标签(数据键值对的键)keyList = stockInfo.find_all('dt')#找到所有dd标签(数据键值对的值)valueList = stockInfo.find_all('dd')for i in range(len(keyList)):key = keyList[i].textval = valueList[i].textinfoDict[key] = val#将新增数据添加到文件with open(fpath, 'a', encoding='utf-8') as f:f.write(str(infoDict)+'\n')count = count + 1print("\r当前进度: {:.2f}%".format(count * 100 / len(stockList)), end="")except:#打印异常信息,这样的做法是 即使出现了异常,异常信息可以显示出来,但是程序仍会接着进行#traceback.print_exc()count = count + 1print("\r当前进度: {:.2f}%".format(count * 100 / len(stockList)), end="")continuedef main():# 股票列表页面(可得到所有股票代号和名称)stock_list_url = 'http://quote.eastmoney.com/stocklist.html'# 个股详细查询页面(根据股票代号可查询)stock_info_url = 'https://gupiao.baidu.com/stock/'# 保存爬取数据的文件output_file = 'BaiduStockInfo.txt'# 股票列表stockList = []# 得到股票列表getStockList(stockList, stock_list_url)# 得到所有个股的详细信息,并保存在输出文件getStockInfo(stockList, stock_info_url, output_file)main()

注意代码中\r的使用技巧:其将输出跳至当前输出的开头,因此可实现“动态进度条”的效果。

【MOOC】Python网络爬虫与信息提取-北京理工大学-part 3相关推荐

  1. python网络爬虫与信息提取北京理工大学_Python网络爬虫与信息提取(一)

    Reference: 第一周 网络爬虫之规则 单元1:Requests库入门 1-1 Requests库的安装 1-2 Requests库的get()方法 1-3 爬取网页的通用代码框架 1-4 HT ...

  2. python网络爬虫与信息提取北京理工大学ppt_北京理工大学Python网络爬虫与信息抽取学习笔记10,信息提取...

    Scrapy爬虫产生步骤 1.建立一个Scrarrpy爬虫工程 cmd命令提示符中选择目录 输入 scrapy start project name #工程名不要含中文,否则之后生成爬虫时会报错 生成 ...

  3. 淘宝商品比价定向爬虫-Python网络爬虫与信息提取-北京理工大学嵩天教授

    功能描述 目标:获取淘宝搜索页面的信息,提取其中的商品名称和价格: 理解:淘宝的搜索接口.翻页的处理: 以课程中的搜索书包为例,对应的url如下: (1)起始页: (2)第二页:最后的s=44: (3 ...

  4. python网络爬虫与信息提取北京理工大学ppt_Python网络爬虫与信息提取

    spContent=理论力学课程组以学生为主体,开展了内容丰富.题材广泛的教学改革与实践研究工作,学生受益量大面广,成效显著.2010年以来编著出版<理论力学>等教材7部9本.承担教研教改 ...

  5. 中国大学MOOC·Python网络爬虫与信息提取_思考小结(一)

    一. 关于requests库用法的几个辨析 1.requests库内分七个函数,分别为 request,get,head,post,put,patch,delete, 其中最经常使用的是:get/he ...

  6. 中国大学MOOC·Python网络爬虫与信息提取(一)

    一.第0周 网络爬虫工具 二.第1周 网络爬虫之规则 1.requests库的安装 打开cmd-输入pip3 install requests 博主遇到的问题:一开始提示不是内部命令也不是外部命令,在 ...

  7. MOOC《Python网络爬虫和信息提取》(第11次)网络爬虫之框架(第4周)

    MOOC<Python网络爬虫和信息提取>(第11次)网络爬虫之框架(第4周) MOOC–Python网络爬虫和信息提取(第11次开课) 网络爬虫之框架 21.08.10 目录 文章目录 ...

  8. 北京理工大学·Python网络爬虫与信息提取·知识整理

    学习目标: python爬虫部分的学习 学习内容: mooc北京理工大学·Python网络爬虫与信息提取 对Scrapy内核依然一知半解,但mooc内容已经学完整理 后续将对Scrapy继续进行学习 ...

  9. python网络爬虫与信息提取_北京理工大学_Python网络爬虫与信息提取(一)

    学习 北京理工大学 嵩天 课程笔记 课程体系结构: 1.Requests框架:自动爬取HTML页面与自动网络请求提交 2.robots.txt:网络爬虫排除标准 3.BeautifulSoup框架:解 ...

最新文章

  1. java g1 gc ref proc_java – 针对sparc T4 8核的正确G1 GC调优
  2. java 写文件的三种方法比较
  3. GO标准库—命令行参数解析FLAG
  4. 从工程师的角度审视 Web 3,没有任何炒作
  5. oracle number +1,number number(1)
  6. 编程中无穷大常量的设定技巧 2014-08-19 09:22 35人阅读 评论(0) 收藏...
  7. JavaScript函数的参数
  8. Vue + Echarts 实现中国地图的绘制
  9. mysql yum 安装
  10. 苹果笔记本安装系统显示英文的解决办法
  11. delphi 隐藏指定程序的托盘图标
  12. 麦田的守望者背景与分析
  13. win10 凭据管理
  14. 浙师大数学与计算机科学学院,王维凡 - 浙江师范大学 - 数学与计算机科学学院...
  15. JSD-2204-VueCLI-Day01
  16. 计算机网络浅谈,浅谈计算机网络的重要性
  17. 快来抄吧:Project Plan Template 项目计划模板
  18. 【机器学习11】LAD,K-means,SVM分析鸢尾花和月亮数据集
  19. [POI2014]DOO-Around the world
  20. [android] 多媒体播放api简介

热门文章

  1. 使用 OpenCV 构建车辆计数器系统
  2. do { } while(){ }
  3. QT+OSG/osgEarth编译之四:libpng+Qt编译(一套代码、一套框架,跨平台编译,版本:libpng-1.6.38)
  4. JS 前端 判断字符串是否相等
  5. js判断字符串为回文
  6. 用CAD绘制奥迪车标
  7. python课设答辩ppt_如何制作优秀的毕业论文答辩 PPT?
  8. R语言做Scheirer–Ray–Hare检验
  9. 纯虚类(virtual class)和纯虚方法(pure virtual function)
  10. js正则表达式 验证手机号,email地址和邮政编码