Python爬虫入门--discussion

这次爬的是牛客网求职论坛上面的岗位信息,在之前爬官方网页时候写过的方法就不在重复啦~~

解析HTML代码

牛客网求职论坛的HTML代码:

我们的处理方式是,前三个不获取,从第四条信息开始:job_div[3:]

每条信息只获取其职位名称(代码中的tittle),然后将每条信息模拟点开,将其中的详细信息获取到;

HTML代码的规律:每条信息都在”div”, {“class”: “discuss-main clearfix”}中,div中的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div class="discuss-main clearfix">
<a href="/discuss/144771?type=7&order=3&pos=5&page=1"
target="_blank">
字节跳动内推码 5GZCACC
</a>
<a href="/discuss/144771?type=7&order=3&pos=5&page=1"
target="_blank">
</a>
<a href="/discuss/tag/665?type=7" class="tag-label"
target="_blank">字节跳动</a>
</div>
<div class="feed-foot">
<div class="feed-origin">
<p class="feed-tip">
<a class="d-name level-color-5
js-nc-card
"
data-card-uid="1529636" href="/profile/1529636
">

我们要做的是:①获取a中的岗位信息(如:字节跳动内推码 5GZCACC)
②模拟点开a中的链接,可以调用之前定义的方法getPageContent(url),然后在对return的内容进行内容的提取。

具体的python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def getJobInfo(page_content):
data=[]
i = 1

job_div = page_content.findAll("div", {"class": "discuss-main clearfix"})
job_div=(job_div[3:])
for links in job_div:
link1=links.find('a')
tittle='\n'+'('+str(i)+')'+'岗位信息:'+link1.get_text().replace('\n','')+'\n' #获取每一条的标题(岗位信息)
i = i + 1
link2='https://www.nowcoder.com'+link1.get('href') #获取每条岗位信息的链接
link3=link2.split('\n')
for req in link3:
xx_1=getPageContent(req)
xx_2=xx_1.findAll("div",{"class":"post-topic-des nc-post-content"})
for req_1 in xx_2:
xx_3='详细介绍:'+(req_1.get_text().replace('-------------------------------------------------------------'
'-------------------------------------------------------------'
'----------------','\n')+'\n').replace('|',' ')+'\n'
xx_3=' '.join(xx_3.split())
xx_4=xx_3.replace('【',('\n'+'【')).replace(' -','\n').replace(' ','\n')
data.append((tittle + xx_4))
for h in data:
print(h)
return data

标序号

由于每条信息爬出来都很多,看起来很乱,所以想对每条信息进行标序,只需在开始定义i=1,然后在获取tittle时加上str(i),然后在后面加上 i = i + 1即可,具体的代码见上面。

split()方法

python split()通过指定分隔符对字符串进行切片,如果参数num有指定值,则仅分隔num个字符串。

语法:

1
str.split(str="",num=string.cout(str))

str:分隔符,默认所有的空字符,包括空格、换行(\n)、制表符(\t)等
num:分割次数

split是对字符串进行处理,返回值是列表list类型的;

本程序中,link3=link2.split('\n'):因为link2是字符串类型,要把它变成list类型,才能在后面对它使用for循环,因此采用split方法,在所有\n的地方分隔开。

link2为:

1
2
3
4
5
https://www.nowcoder.com/discuss/140290?type=7&order=3&pos=4&page=2
https://www.nowcoder.com/discuss/144831?type=7&order=3&pos=5&page=1
https://www.nowcoder.com/discuss/144830?type=7&order=3&pos=6&page=1
https://www.nowcoder.com/discuss/144817?type=7&order=3&pos=7&page=0
https://www.nowcoder.com/discuss/144788?type=7&order=3&pos=8&page=1

经过split方法后,得到的link3为:

1
2
3
4
5
['https://www.nowcoder.com/discuss/140290?type=7&order=3&pos=4&page=2']
['https://www.nowcoder.com/discuss/144831?type=7&order=3&pos=5&page=1']
['https://www.nowcoder.com/discuss/144830?type=7&order=3&pos=6&page=1']
['https://www.nowcoder.com/discuss/144817?type=7&order=3&pos=7&page=0']
['https://www.nowcoder.com/discuss/144788?type=7&order=3&pos=8&page=1']

join()方法

因为打印出来的详细信息格式非常乱,每一句中间隔了好多的空格,如下所示:

为了解决这种现象,用到了下面这个函数,xx_3=' '.join(xx_3.split())

其中,先介绍一下python join()方法,用于将序列中的元素以指定的字符连接成一个新的字符串。
语法: str.join(sequence)

sequence–要连接的元素序列

返回通过指定字符连接序列中元素后,生成的新的字符串。

注:str.join(元组、列表、字典、字符串)之后生成的只能是字符串。所以有时候可以用join方法将元组、列表这些变成字符串。

接着上面的问题,先对xx_3经进行split方法,即

1
2
xx_3=xx_3.split()
print(xx_3)

处理后的结果为,可以看出把所有的空格处切为一个个的字符串

然后再用join方法可以把上面的每个字符串之间用一个空格连接起来,就把之前句子与句子之间的多个空格变成了一个空格,问题解决。

append()方法

append方法用于在列表末尾添加新的对象。
后面的做法就是把岗位信息和详细信息用append方法加在data(之前定义的空列表上),然后一条一条打印出来。

python中常用的数据结构学习

列表list

Python中列表是可变的,这是它区别于字符串和元组的最重要的特点,一句话概括即:列表可以修改,而字符串和元组不能。

list是python内置的一种数据类型列表,是一种有序的集合,可以随时添加和删除其中的元素。

和Java相比的不同点:

1.如果要取最后一个元素,除了计算索引位置外,还可以用-1做索引,直接获取最后一个元素: 、

1
2
3
4
classmates=['肖洒','美洒','洒哥哥']
print(classmates[-1])

输出---洒哥哥

2.可以把元素插入到指定的文职,比如索引号为1的位置:

1
2
3
4
5
classmates=['肖洒','美洒','洒哥哥']
classmates.insert(1,'铁丑')
print(classmates)

输出---['肖洒', '铁丑', '美洒', '洒哥哥']

3.要删除list末尾的元素,用pop()方法,删除指定位置的元素,用pop(i)方法,其中i是索引位置。

4.list里面的元素的数据类型也可以是不同的:

1
L=['apple','123','True']

5.list元素也可以是另一个list:

1
2
3
4
s=['python','java',['肖洒','美洒','洒哥哥'],'c++']
print(len(s))

输出--4

元组tuple和序列

tuple和list非常相似,但是tuple一旦初始化就不能修改。因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。

元组由若干逗号分隔的值组成,例如:

1
2
3
4
5
6
7
8
9
>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))

如你所见,元组在输出时总是有括号的,以便于正确表达嵌套结构。在输入时可能有或没有括号, 不过括号通常是必须的(如果元组是更大的表达式的一部分)。

需要注意的地方:

1.只有1个元素的tuple定义时必须加一个逗号,来消除歧义:

1
2
3
4
t=(1,)
print(t)

输出---1

2.也存在“可变的”tuple:

1
2
3
4
5
6
t = ('a', 'b', ['A', 'B'] )
t[2][0] = 'X'
t[2][1] = 'Y'
print(t)

输出---('a', 'b', ['X', 'Y'])

这个tuple定义的时候有3个元素,分别是’a’,’b’和一个list。

当我们把list的元素’A’和’B’修改为’X’和’Y’后,tuple变为:

表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向’a’,就不能改成指向’b’,指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!

集合set

集合是一个无序不重复元素的集。基本功能包括关系测试和消除重复元素。可以用大括号({})创建集合。注意:如果要创建一个空集合,你必须用 set() 而不是 {} ,后者创建一个空的字典。

字典dict

序列是以连续的整数为索引,与此不同的是,字典以关键字为索引,关键字可以是任意不可变类型,通常用字符串或数值。理解字典的最佳方式是把它看做无序的键=>值对集合。在同一个字典之内,关键字必须是互不相同。 一对大括号创建一个空的字典:{}。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'sape': 4139, 'guido': 4127, 'jack': 4098}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'guido': 4127, 'irv': 4127, 'jack': 4098}
>>> list(tel.keys())
['irv', 'guido', 'jack']
>>> sorted(tel.keys())
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
>>> 'jack' not in tel
False

遍历技巧

在字典中遍历时,关键字和对应的值可以使用 items() 方法同时解读出来:

1
2
3
4
5
6
knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.items():
print(k, v)

输出---gallahad the pure
robin the brave

在序列中遍历时,索引位置和对应值可以使用 enumerate() 函数同时得到:

1
2
3
4
5
6
7
for i, v in enumerate(['tic', 'tac', 'toe']):
print(i, v)

输出:
0 tic
1 tac
2 toe

同时遍历两个或更多的序列,可以使用 zip() 组合:

1
2
3
4
5
6
7
8
9
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
print('What is your {0}? It is {1}.'.format(q, a))

输出:
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.

要反向遍历一个序列,首先指定这个序列,然后调用 reversed() 函数:

1
2
3
4
5
6
7
8
9
for i in reversed(range(1, 10, 2)):
print(i)

输出:
9
7
5
3
1

要按顺序遍历一个序列,使用 sorted() 函数返回一个已排序的序列,并不修改原值:

1
2
3
4
5
6
7
8
9
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
print(f)

输出:
apple
banana
orange
pear