python渐入佳境

网络爬虫之前,我们应先明白:
     首先要进行网页请求,这时就要用到requests库:
例:
>>>r=requests.get("http://www.baidu.com")
>>>r.status_code        #返回状态
200
>>>r.text
(这里会输出请求的页面内容,包含中文字符会出现乱码)
>>>r.encoding='utf-8'
>>>r.text
(这里输出请求的页面内容,包含中文字符将不会出现乱码)

有关以上内容的几点重要讲解:
1.requests.get(url)来读取指定网页的信息,这是最基本的不带参数的get请求,在调用它后,返回的网页内容会保存为一个reponse对象。
2.requests.get(url,params),这是带参数的get请求,作用是向url传递参数(这一点不懂)。
3.对于第一点提出的response,它有四个属性:
        (1)status_code: 表示http请求的返回状态,整数200表示连接成功,而404表示失败。在处理数据之前要先判断状态情况,如果请求未被响应,需要终止内容处理。
        (2)encoding: 这一属性特别重要,(之前便有学姐给另外一个学生讲解,我不知道说的是什么!这次明白了)它是http响应内容的编码方式,当我们处理中文字符的时候,我们需要更改编码方式为utf-8。
        (3)text: http响应内容的字符串形式,即url对应的页面内容。
        (4)content:http响应内容的二进制形式(这个也不清楚它的意思,百度了也没弄懂)。

     在使用requests库获得html页面后(即获得网页请求内容,将其转换成字符串后),需要进一步解析html页面格式,提取html标签中的有用信息,这时需要处理html的函数库:BeautifulSoup4库(原来它与html关系匪浅啊::BeautifulSoup属性与html的标签名称是相同)。上一周python学习关于它有一些简单的介绍,这次就必须延伸一下了,(以下的代码是我根据教材写的,主要是想弄清楚每一条语句的作用效果,这样自己单独爬虫才知道原理;虽然是“抄”别人的,但是我也是一步一步实践(这样印象才深刻),每一步都弄明白了才进行下一步的):
>>>import requests
>>>from bs4 import BeautifulSoup
>>>r=requests.get("http://www.baidu.com")
>>>r.encoding="utf-8"
>>>soup=BeautifulSoup(r.text)                #soup就是一个BeautifulSoup对象
>>>soup.head                                #获取html页面中的head内容
<head><meta content="text/html;charset=utf-8" http-equiv="content-type"/><meta content="IE=Edge" http-equiv="X-UA-Compatible"/><meta content="always" name="referrer"/><link href="http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/><title>百度一下,你就知道</title></head>
>>>soup.title                                #获取html页面中的head内容中的标题title
<title>百度一下,你就知道</title>
>>>soup.head.name  #获取标签的名字
head
>>>soup.title.string                                 #获取我们一般需要爬取的信息文字,(重中之重)
百度一下,你就知道
另附操作实图:    

在上述实践中,我本来想写
>>>soup.head.string  
但是回应的内容却是None
查到资料:由于html语法可以在标签中嵌套其他标签,所以string属性的返回值,遵循如下原则:
      (1)如果标签内部没有其他标签,string属性返回其中的内容;
      (2)如果标签内部还有其他标签,但只有一个标签,html属性返回最里面标签的内容;
      (3)如果标签内部有超过一层嵌套的标签,string属性返回None(空字符串)。
所以我收到None的原因是原则三。

      接下来,我用BeautifulSoup方式爬取东方财富网(由于软件出了一些问题(软件pycharm每次只能运行30分钟会退出,且有些第三方库说是因为版本问题,导入失败,提醒卸载重新安装,还是没有成功,误操作了后,所有的第三方库都不见了,想重新引进,发现点击不了,以至于在Pycharm中写出的python一点都不行了。后来学姐给了我一个Anaconda软件,安装后,它底下的所有文件都打不开,百度了,还是不成功,后来由于时间问题,就暂且没有解决了),这些问题有点解决不了(解决了好久,感觉每周都浪费在这些软件本身的问题上了),我只能人工翻译代码,还没执行过,但尽我所能理解写出来。) 
import requests              
from bs4 import BeautifulSoup     
import csv    #引入库文件
url='http://data.eastmoney.com/bbsj/201806/yjbb.html'        #获取要爬取的网址
req=requests.get(url)
html1=req.concent       #可以把html网页的源代码爬下来,但是会出现网页乱码的现象,于是我们就要调整网页的编码
req.encoding=req.apparent_encoding
html2=req.text    #这个是获取URL的页面内容
soup=BeautifulSoup(html2,'lxml')      #用BeautifulSoup方法解析文件
h101=soup.find_all(class_='h101)               
for each in h101:
    h101_list=[]
    h101_list.append(each.string)
    h101_list.append(each.get('href'))                     #对于这个for循环我不知道对不对,主要是获取html标签中的文字信息,保存在一个文件库里


对于以上代码,没有存在MySQL里,我总感觉代码少了些,但是我不知道少了些啥?先搁置!


正则表达式方式爬取东方财富网:
首先要明白:正则表达式描述了一种字符串匹配的模式,
          1. 给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”);
           2. 可以通过正则表达式,从字符串中获取我们想要的特定部分。

re模块的方法(重要):
     1. re.match(pattern,string,flags=0): 用于尝试从字符串的起始位置匹配一个正则表达式,如果匹配成功则返回一个match对象,如果没有匹配成功,就返回None。其中pattern指的是匹配的正则表达式,string指的是用于匹配的字符串,flags是标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
      接下来就以match方法为测试对象教大家书写一个正则表达式。首先我给出一个简单的字符串'hello world',大家看什么样的正则表达式能匹配它,我先给出一个,大家请看:

(补充:Match对象的group(0)用于返回匹配的整个字符串,span()方法用于以元祖形式返回匹配的起始位置和结束位置。)
其中'hello world'也是一个正则表达式,它能匹配字符串'hello world'或以'hello world'开头的字符串。
此外,又有如何匹配下面三个字符串:
>>>s1='Tom'
>>>s2='Tim'
>>>s3='Toooooom'
>>>m=r'T[io]+m'                     #注意这一行,匹配的 书写格式, 是要以r开头;
>>>re.match(m,s1) .group(0)
'Tom'
>>>re.match(m,s2) .group(0)
'Tim'
>>>re.match(m,s3) .group(0)
'Toooooom'
>>>re.match(m,'Tuplm') .group(0)#可以看到以上的三个字符串都能匹配出来,但是第四个就不行,是因为第四个Tuplm不满足匹配式'T[io]+m' ,虽然首尾满足,但是中间出现了除i和o以外的字母。
'error'
对于以上的匹配式中的关键部分即中间的 [io]+,[io]表示匹配的字符可以是中括号中的任意一个i或o,而后面跟着的+号(+号详见后面的介绍!)表示可以对[io]匹配一次或多次。所以只要满足这一条件的字符串都是可以被匹配的。
接下来写一个正则表达式,用来匹配仅以数字组成的字符串:

符号^匹配行首,符合$匹配行尾(有关补充见后面),中括号里的内容表示字符串中所能包括的字符,不过,这样写有点笨拙,若写一个能匹配所有仅以字母组成的字符串的正则表达式,26个字母写全加上大写,一共52个,多费劲。不过此时Python却支持这样:

       2.re.findall(pattern, string[, flags]): 能够以列表的形式返回能匹配的子串。先看简单的例子:
>>>import re
>>>a = 'one1two2three3four4'
>>>ret = re.findall(r'(\d+)',a)
>>>print(ret)
['1', '2', '3', '4']
从上面的例子可以看出返回的值是个列表,并且返回字符串中所有匹配的字符串。 
      3.re.finditer(pattern, string[, flags]):搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。 请看例子:
>>>import re
>>>p = re.compile(r'\d+')          #匹配数字
>>>for m in p.finditer('one1two2three3four4'):
>>> print m.group()
1 2 3 4 
      4.re.split(pattern, string, maxsplit=0):通过正则表达式将字符串分离。如果用括号将正则表达式括起来,那么匹配的字符串也会被列入到list中返回。maxsplit是分离的次数,maxsplit=1分离一次,默认为0,不限制次数。看一下例子:>>>import re
>>>ret = re.split('\d+','one1two2three3four4') #匹配到1的时候结果为'one'和'two2three3four4',匹配到2的时候结果为'one', 'two'和'three3four4', 所以结果为:
['one', 'two', 'three', 'four', '']


      正则表达式是由普通字符(包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号)以及特殊字符(称为"元字符":所谓特殊字符,就是一些有特殊含义的字符,如下面说的 runoo*b 中的 *,简单的说就是表示任何字符串的意思)组成的文字模式;可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等,例如:

runoo+b,可以匹配 runoob、runooob、runoooooob 等,+ 号代表前面的字符必须至少出现一次(1次或多次)。
runoo*b,可以匹配 runob、runoob、runoooooob 等,* 号代表字符可以不出现,也可以出现一次或者多次(0次、或1次、或多次)。
colou?r 可以匹配 color 或者 colour,? 问号代表前面的字符最多只可以出现一次(0次、或1次)

然后,我又看到一些总汇,如下:

*          匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。

+         匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。

?        匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" 。? 等价于 {0,1}。

{n}        n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。

{n,}       n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。 

{n,m}    m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。

接下来我补充一些我能看懂的:
1.  \ba\w*\b匹配以字母a开头的单词——先是某个单词开始处(\b),然后是字母a,然后是任意数量的字母或数字(\w*),最后是单词结束处(\b)。
2.  \d+匹配1个或更多连续的数字。这里的+是和*类似的元字符,不同的是*匹配重复任意次(可能是0次),而+则匹配重复1次或更多次。
3.  \b\w{6}\b 匹配刚好6个字符的单词。
4.元字符^(和数字6在同一个键位上的符号)和$都匹配一个位置,这和\b有点类似。^匹配你要用来查找的字符串的开头,$匹配结尾。这两个代码在验证输入的内容时非常有用,比如一个网站如果要求你填写的QQ号必须为5位到12位数字时,可以使用:^\d{5,12}$。{5,12}是重复的次数不能少于5次,不能多于12次,否则都不匹配。因为使用了^和$,所以输入的整个字符串都要用来和\d{5,12}来匹配,也就是说整个输入必须是5到12个数字,因此如果输入的QQ号能匹配这个正则表达式的话,那就符合要求了。

5.

字符   说明
.匹配除换行符以外的任意字符
\w匹配字母或数字或下划线或汉字
\s匹配任意的空白符
\d匹配数字
\b匹配单词的开始或结束
^匹配字符串的开始
$匹配字符串的结束


6.   0\d{2}-\d{8}|0\d{3}-\d{7}这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号(0376-2233445)。


有如下:
>>>list1=['hppss','python','pyinfo','pygame','apple']            #怎么样才能在列表list1中找出以py开头的字串呢
可以这样做:

 

以上方法似乎可以行通,但是如果有:字符串'ab23fd5g67',我们需要提取出23、5、67,且不能分开,这个时候用以上方法恐怕是不容易的,这样就需要正则表达式出场:
>>>m=r'^[0-9]+$'
>>>re.match(m,'ab23fd5g67').group(0)
23567

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值