简单利用python爬取网站数据

Posted by DoubleWay on May 15, 2020

简单利用python爬取网站数据

import requests
page=requests.get('https://www.baidu.com/')
print(page.text)

首先就是这最简单的这三行python代码

import request导入我们需要的功能模块,request的功能就是我们向互联网发送请求和获取数据的

page=requests.get(‘https://www.baidu.com/’)这句就是表示获取百度网站首页的数据

print(page.text)把我们获取到的网页数据输出出来

<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>ç™¾åº¦ä¸€ä¸‹ï¼Œä½ å°±çŸ¥é“</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> 
//...........

可以看到,将网页的信息打印了出来,就是要从网页的源码信息中,提取出我们需要的信息

这里以豆瓣电影TOP250网页为例

# -*- coding: utf-8 -*-
import requestshaiyou
from lxml import etree
from bs4 import BeautifulSoup
import sys

reload(sys)
sys.setdefaultencoding('utf-8')
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'}
start=0
f=open('/home/android/tmp/1.txt','a+')
for n in range(0,10):
  html = requests.get("https://movie.douban.com/top250?start="+str(start),headers=headers)
  start += 25
  soup = BeautifulSoup(html.text, 'html.parser')
  for item in soup.find_all('div',"info"):
    title = item.div.a.span.string  # 获取标题
    yearline = item.find('div', 'bd').p.contents[2].string
    yearline = yearline.replace(' ', '')  # 去掉这一行的空格
    yearline = yearline.replace('\n', '')  # 去掉这一行的回车换行
    year = yearline[0:4]  # 只取年份前四个字符
    print(title+'\t'+year)
    f.write(title+'\t'+year+'\n')
f.close()

上面的代码解释的话就是

# -*- coding: utf-8 -*-

如果要在python2的py文件里面写中文,则必须要添加一行声明文件编码的注释,否则python2会默认使用ASCII编码。

import requests
from lxml import etree
from bs4 import BeautifulSoup
import sys

这是导入需要的功能模块,from bs4 import BeautifulSoup的意思就是bs4不需要全部导入,只需要其中的BeautifulSoup模块

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

是解决在文件写入时,非ascii编码报错的问题, python在安装时,默认的编码是ascii,当程序中出现非ascii编码时,python的处理常常会报这样的错UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0x?? in position 1: ordinal not in range(128),python没办法处理非ascii编码的,此时需要自己设置将python的默认编码,一般设置为utf8的编码格式。

headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'}

这是在获取网站信息的时候添加的头部信息,因为一些网站拥有反爬虫机制,一些网站会根据headers来判断是否是爬虫,所以我们要伪装headers信息。如果是通过requset来请求网站的话,

例如:

import requests
html = requests.get("https://blog.csdn.net/it_xf?viewmode=contents")
print(html.request.headers)

得到的结果是:

{'Connection': 'keep-alive', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.23.0'}

而像豆瓣这种具有判断爬虫机制的网站,右键检查–>network,刷新一下,看它的herdaers

2020-05-15-1.1

所以我们想要绕开这个反爬措施的时候,就要将自己伪装成游览器,将他的headers替换自己的headers,然后添加到请求后面

html = requests.get("https://movie.douban.com/top250?start="+str(start),headers=headers)
start=0
f=open('/home/android/tmp/1.txt','a+')
for n in range(0,10):
  html = requests.get("https://movie.douban.com/top250?start="+str(start),headers=headers)
  start += 25
  soup = BeautifulSoup(html.text, 'html.parser')
  for item in soup.find_all('div',"info"):
    title = item.div.a.span.string  # 获取标题
    yearline = item.find('div', 'bd').p.contents[2].string
    yearline = yearline.replace(' ', '')  # 去掉这一行的空格
    yearline = yearline.replace('\n', '')  # 去掉这一行的回车换行
    year = yearline[0:4]  # 只取年份前四个字符
    print(title+'\t'+year)
    f.write(title+'\t'+year+'\n')
f.close()

这后面的主要就是主要的功能代码,f=open('/home/android/tmp/1.txt','a+'),打开一个1.txt文件,如果没有就创建,模式是a+,

模式 可做操作 若文件不存在 是否覆盖
r 只可读 报错 -
r+ 可读可写 报错
w 只可写 创建
w+ 刻度可写 创建
a 只可写 创建 否,追加
a+ 可读可写 创建 否,追加

for n in range(0,10):循环,range(0,10)是生成一个0-9的集合

soup = BeautifulSoup(html.text, 'html.parser')BeautifulSoupbs4里面的功能模块,这里就是调用html的parser(解析器),来解析我们获取的网页html的文字内容,soup就是解析的结果。

for item in soup.find_all('div',"info"):这里又是一个循环,在我们获得了解析到的网页内容后,调用soup的find_all方法来查找全部,查找全部标记名为div,class的值是info的元素的值

title=item.div.a.span.string中item代表的是上面图片中的整个div元素(class=’info’),它的下一层div的下一层a的下一层span的“肖申克的救赎”就是我们需要的内容,但是一层层的点下去的方法只适合于获取到每层的第一个元素,比如我们知道实际有三个span,其他两个英文名、其他译名,但我们只取到第一个。

yearline = item.find('div', 'bd').p.contents[2].string就是调用了.find,.p方法,contents[2]是取得这一行第3个文字小节,content单词是内容的意思, br标记将整个p标记内容分成了三段(0段,1段,2段)。

f.write(title+'\t'+year+'\n')将内容写入文件中

肖申克的救赎	1994
霸王别姬	1993
阿甘正传	1994
这个杀手不太冷	1994
美丽人生	1997
泰坦尼克号	1997
千与千寻	2001
辛德勒的名单	1993
盗梦空间	2010
忠犬八公的故事	2009
海上钢琴师	1998
楚门的世界	1998