网页数据抓取怎么写(Python多线程抓取数据(一)|本篇)

优采云 发布时间: 2022-02-10 15:19

  网页数据抓取怎么写(Python多线程抓取数据(一)|本篇)

  我会多方面讲解大数据职业学习的理论,做到最好的文章讲解。感谢您的赞赏。[本文文章转载于博客园:susmote]。评论要求博主转发。

  在这篇文章文章中,我们主要介绍多线程数据捕获。

  

  多线程以并发方式执行。这里需要注意的是,Python中的多线程程序只能以并发的方式在单核上运行,即使在多核机器上也是如此。因此,使用多线程抓取可以极大的提高抓取效率

  接下来我们以requests为例介绍多线程爬取,然后和单线程程序进行对比,体验多线程效率的提升

  我们通过当当网测试了我们的多线程实例,并演示了搜索结果同爬的功能。搜索方式地址如下

  1

  

  可以看到key代表搜索关键字,act代表你是怎么搜索的,page_index代表搜索页面的页码

  

  抓取上述页码后,提取其中的信息,最后将提取的信息保存在一个文本文件中,其中保存了每本书的标题及其链接

  下面我们定义抓取实验所需的方法(或函数)

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  11

  12

  13

  14

  15

  16

  17

  18

  19

  20

  21

  22

  二十三

  24

  25

  26

  27

  28

  29

  30

  31

  32

  33

  34

  35

  36

  37

  38

  39

  # 编码=utf-8

  __Author__ =“支持”

  导入请求

  从 bs4 导入 BeautifulSoup

  但还是不得不说博主真的很不错!

  def format_str(s):

  返回 s.replace("\n", "").replace(" ", "").replace("\t", "")

  def get_urls_in_pages(from_page_num, to_page_num):

  网址 = []

  search_word = "蟒蛇"

  url_part_1 = ""

  url_part_2 = "&act=输入"

  url_part_3 = "&page_index="

  对于我在范围内(from_page_num,to_page_num + 1):

  urls.append(url_part_1 + search_word + url_part_2 + url_part_3 + str(i))

  all_href_list = []

  对于网址中的网址:

  打印(网址)

  resp = requests.get(url)

  bs = BeautifulSoup(resp.text, "lxml")

  a_list = bs.find_all("a")

  需要列表 = []

  对于 a_list 中的一个:

  如果 a.attrs 中的“名称”:

  name_val = a['name']

  href_val = a['href']

  标题 = a.文本

  如果 name_val 和 title 中的 'itemlist-title' ! = "":

  如果 [title, href_val] 不在 required_list 中:

  required_list.append([format_str(title), format_str(href_val)])

  all_href_list += required_list

  all_href_file = open(str(from_page_num) + '_' + str(to_page_num) + '_' + 'all_hrefs.txt', 'w')

  对于 all_href_list 中的 href:

  all_href_file.write('\t'.join(href) + '\n')

  all_href_file.close()

  打印(from_page_num,to_page_num,len(all_href_list))

  下面解释一下代码

  首先,format_str用于提取信息后去除多余的空格

  get_url_in_pages 方法是执行函数的主体。该方法接收的参数是指页码的范围。在函数体中,urls主要用于存储根据这两个参数生成的所有待爬取页面的链接。我把url分成3部分也是为了方便后面的链接组合,然后for循环就是做拼接的工作。我不会在这里解释它。如果不明白,请留言。

  接下来,我们定义一个列表all_href_list,这个列表用来存放每一页收录的书籍信息,实际上是一个嵌套列表,里面的元素是[书名,链接],他的形式如下图

  1

  2

  3

  4

  5

  6

  all_href_list = [

  ['标题1',“链接1”],

  ['标题2',“链接2”],

  ['标题 3',“链接 3”],

  ……

  ]

  这文章我达不到这个水平

  下面的代码是从一个页面爬取和提取信息。这部分代码在for url in urls的循环体中,先打印链接,然后调用requs的get方法获取页面,再使用BeautifulSoup获取页面。将get请求返回的HTML文本进行分析,转换成BeautifulSoup可以处理的结构,命名为bs

  之后,我们定义的needed_list用来存放书名和链接。bs.find_all('a') 提取页面中的所有链接元素,for a in a_list 遍历并分析每个列表中的元素。在此之前,我们通过浏览器找到了他的结构。

  

  每个书本元素都有一个值为“itemlist_title”的属性名称。通过这个,我们可以很方便的过滤出书本元素,然后将书本信息和链接元素href一起存储到列表中。在它存在之前,我们也做一些判断,这个链接是否已经存在,有这个元素的链接是否为空

  一个页面的每个链接提取出来后,可以添加到all_href_list,也就是下面这行代码

  1

  all_href_list += required_list

  注意我在这里使用 += 运算符

  获取范围内的所有链接元素后,您可以写入文件。我不会在这里过多解释。

  那么我们下一步就是定义多线程了,因为我们搜索关键词的总页数是32页

  

  所以这里我们要用3个线程来完成这些任务,也就是每个线程处理10个页面。在单线程的情况下,这30页是一个线程单独完成的

  下面我们给出爬取方案的代码

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  11

  12

  13

  14

  15

  16

  17

  18

  19

  20

  21

  22

  二十三

  24

  25

  26

  27

  28

  29

  # 编码=utf-8

  __Author__ =“支持”

  哎,刷一波存在

  *敏*感*词*时间

  导入线程

  从 Mining_func 导入 get_urls_in_pages

  def multiple_threads_test():

  start_time = time.time()

  page_range_list = [

  (1, 10),

  (11, 20),

  (21, 32),

  ]

  th_list = []

  对于 page_range_list 中的 page_range:

  th = threading.Thread(target = get_urls_in_pages, args = (page_range[0], page_range[1]))

  th_list.append(th)

  对于 th_list 中的 th:

  th.start()

  对于 th_list 中的 th:

  th.join()

  end_time = time.time()

  print("总使用时间 1:", end_time - start_time)

  返回结束时间 - 开始时间

  简单解释一下,为了得到运行时间,我们定义了一个开始时间start_time和一个结束时间end_time,运行时间就是结束时间减去开始时间

  然后定义一个列表page_range_list,将页码分成三段,如前所述

  之后定义了一个列表th_list,它是所有线程对象的列表,然后通过循环生成三个线程对象,分别对应不同的页码范围,并存储在列表中。

  然后在下面的循环中,分别执行th.start()来启动线程。在后者中,我们退出函数是为了让这些异步并发执行的线程全部执行,这里我们使用线程的join方法等待每个线程执行。完全的

  现在是测试代码最激动人心的时刻

  在这里,我们编写如下代码

  1

  2

  3

  4

  5

  6

  7

  8

  # 编码=utf-8

  __Author__ =“支持”

  我又喘不过气来了

  从 Mining_threading 导入 multiple_threads_test

  如果 __name__ == "__main__":

  mt = multiple_threads_test()

  打印(“吨”,吨)

  为了使测试结果更加准确,我们进行了三个实验,取平均时间

  第一次实验

  

  使用时间6.651

  第二次实验

  

  使用时间6.876

  第三次实验

  

  使用时间6.960

  平均时间如下

  

  6.829

  下面是单进程代码

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  11

  12

  13

  # 编码=utf-8

  __Author__ =“支持”

  *敏*感*词*时间

  从 Mining_func 导入 get_urls_in_pages

  你觉得 文章 很棒吗

  def sigle_test():

  start_time = time.time()

  get_urls_in_pages(1, 32)

  end_time = time.time()

  print("总使用时间:", end_time - start_time)

  返回结束时间 - 开始时间

  调用函数如下

  1

  2

  3

  4

  5

  6

  7

  8

  9

  # 编码=utf-8

  __Author__ =“支持”

  从 single_mining 导入 single_test

  不火就受不了了吗?

  如果 __name__ == "__main__":

  st = single_test()

  打印('st',st)

  在命令行执行

  第一次

  

  10.138

  第二次

  

  10.290

  第三次

  

  10.087

  平均花费时间

  

  10.171

  所以,多线程确实可以提高爬取的效率。请注意,这是在数据相对较小时完成的。如果数据量比较大,多线程的优势就很明显了。

  你可以自己改搜索关键词,和页码,或者找一个新的网页(爬也跟网速有很大关系)

  附上几张捕获数据的图片

  

  

  像往常一样,如果你想知道如何学习大数据,可以私聊我,每次你的认可都是对我很大的鼓励。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线