python 爬虫入门

三个流程

  • 获取网页
  • 解析网页
  • 存储数据

获取网页

获取网页的基础:requests、urllib、selenium
进阶:多线程、登录抓取、突破ip封禁、使用服务器抓取

解析网页

基础:re正则表达式、Beautiful、lxml
进阶:解决中文乱码

存储数据

基础:存入txt和csv文件
进阶:存入MySQL\MongoDB数据库

或者直接用Scrapy框架。

编写一个简单的爬虫

import requests
import time
from bs4 import BeautifulSoup

link="http://www.santostang.com//"
headers={'User-Agent':'Mozilla/5.0(Windows;U;Windows NT6.1;en-US;rv:1.9.1.6) Gecko/20091201 Firefox/3.5.7'}
r=requests.get(link,headers=headers)
print(r.text)
soup=BeautifulSoup(r.text,"html.parser")
time.sleep(10)
title=soup.find("h1",class_="post-title").a.text
print(title)
with open('title_test.txt',"a+") as f:
	f.write(title)

学会用浏览器菜单栏中的检查菜单来查看浏览器的html语句

其中,requests.get说获取相应的相应内容。只使用它只能读取网页的一些设置值,如语言设置、响应状态值等等。

定制Requests

这一节主要是解决有些网页必须设置了部分参数之后才能进行获取,这部分的内容包括传递URL参数、定制请求头、发送POST请求、设置超时等等。

传递URL参数

在获取代码中修改成如下带有参数的请求

key_dict={'key1':'value1','key2':'value2'}
r=requests.get('http://httpbin.org/get',params=key_dict)

就形成了我们需要的URL格式

http://httpbin.org/get?key1=value1&key2=value2

定制请求头

这部分的内容需要使用浏览器的检查-Network 可以看到请求头的具体信息,将请求头的内容给到requests.get获取函数里面的headers部分即可。

发送POST请求

与GET的不同在于,get请求的参数回跟在URL后面,在有重要密码等参数时就很不安全。
发送POST请求的规则如下:

key_dict={'key1':'value1','key2':'value2'}
r=requests.post('http://httpbin.org/get',data=key_dict)

超时

限制访问网页的时间。
只要在请求函数后面加上

timeout= 具体值

爬取豆瓣代码

import requests
import time
from bs4 import BeautifulSoup
def get_movies():
    headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0',
           'Host':'movie.douban.com'}
    movie_list=[]
    for i in range(0,10):
        link='http://movie.douban.com/top250?start='+str(i*25)
        
        r=requests.get(link,headers=headers,timeout=10)
        time.sleep(1)
        #print(str(i+1),"页相应状态码",r.status_code)
        
        soup=BeautifulSoup(r.text,"lxml")
        div_list=soup.find_all('div',class_='hd')
        for each in div_list:
            movie=each.a.span.text.strip()
            movie_list.append(movie)
    return movie_list
movies=get_movies()
print(movies)

动态网页抓取

在学习之前需要了解异步更新技术——AJAX,它的价值在于通过少量的代码就可以使网页实现异步更新,即网页的部分更新(内容变化,但url没变)。这样网页的抓取就显得繁复,我们可以以爬取网页的评论来了解动态网页抓取的过程。(一般用JavaScript)
一般用

  • 浏览器审查元素解析地址
  • 通过Selenium模拟浏览器抓取

浏览器审查

首先给出完整代码

import json
import requests
link="https://api-zero.livere.com/v1/comments/list?callback=jQuery112405130785675025886_1620273279720&limit=10&repSeq=4272904&requestPath=%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1620273279722"
header={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0'}
r=requests.get(link,headers=header)
json_string=r.text
json_string=json_string[json_string.find('{'):-2]
json_data=json.loads(json_string)
comment_list=json_data['results']['parents']
for eachone in comment_list:
    message=eachone['content']
    print(message)

1.虽然数据没有出现在网页源代码中,但还是可以在网页-检查中找到所想要的数据,需要找到真正的评论文件进行爬取。
2.获取到数据以后发现是乱码,所以还需要用json进行解析。

json_string[json_string.find(’{’):-2]

就是仅仅提取字符串中符合json的部分,接着用json.loads可以把字串格式的响应体数据转化成json数据。利用其结构我们可以提取评论的列表comment_list。

通过Selenium模拟浏览器进行抓取

主要解决了之前那种方法找不到真是源代码的情况。可以模拟浏览器加载页面,同时抓取数据,这样就把动态页面的获取变成了静态。
1.用对应驱动打开页面,代码如下

from selenium import webdriver
driver = webdriver.Firefox(executable_path=r'C:\Users\Gray\Desktop\geckodriver.exe')
driver.get("http://www.santostang.com/2018/07/04/hello-world/")

这一部分在jupyter中运行时可能报错,因为现在版本的selenium没有了geckodriver,要下载后运行上面程序(路径地址一定要搞对),运行之后就可以代开对应的网页,实现模拟浏览器。

comment=driver.find_element_by_css_selector('div.reply-content')
content=comment.find_element_by_tag_name('p')

这一部分是通过css选择器取取class为reply-content,tag为p的文本。
但是运行之后这部分的内容还是不对,这是因为原来代码中的javascript的内容解析到了一个iframe框架当中,所以找不到div.reply-content。因此还需要对框架进行解析

driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))
comment=driver.find_element_by_css_selector('div.reply-content')
content=comment.find_element_by_tag_name('p')

selenium还可以模拟浏览器进行下滑和点击,本篇文章仅仅用来入门。

高级操作(待补充)

  • 控制CSS的加载
  • 控制图片文件的显示
  • 控制JavaScript的运行

解析网页

  • 实用正则表达式
  • BeautifulSoup
  • lxml

正则表达式

关于正则表达式的内容在我的另一篇文章里面有写,这里我们主要写怎么用来解析网页。
在这里插入图片描述

re.match

import re
m=re.match(‘www’,‘www.santostang.com’,flags=0)
print(m.span)
print(m.start)
print(m.end)

也能将第一个参数换成正则表达式的形式。(匹配时一般会采用贪婪匹配的形式),匹配之后通过group来调用。group(0)就是原来的字符串,1就是左边,1就是右边,无就是都取。在正则匹配时一般字符串需要经过字串转义和正则转义。

re.search

re.match只能从字串的起始位置开始匹配,而re.search可以扫描整个字符串并返回第一个成功的匹配。具体参数设置方式与re.match一样。

re.findall

它的优势在于可以找到所有匹配的结果并以列表显示出来,而前面两个只能找出一个。
re.findall(’<><>(.*?)<>’,text),只提取括号里面的内容。(还需要后续学习html之后补充)

BeautifulSoup

from bs4 import BeautifulSoup

它是一个工具箱,提供了标准库中的HTML解析器html.parser、和一些第三方解析器,如"lmxl"
第三方解析器还有[“lmxl”,“xml”]、“html5lib”(容错性最好)等等

方法

import requests
from bs4 import BeautifulSoup
link="http://www.santostang.com//"
headers={'User-Agent':'Mozilla/5.0(Windows;U;Windows NT6.1;en-US;rv:1.9.1.6) Gecko/20091201 Firefox/3.5.7'}
r=requests.get(link,headers=headers)
soup=BeautifulSoup(r.text,"lxml")
first_title=soup.find("元素名"class="具体class").a.text.strip()

还可以

soup.find_all(“元素名”,class=“具体class”)

返回一个列表。

其他功能

美化:soup.prettify()

遍历文档数

soup.header.h1
soup.header.div.contents #把它的子节点用列表方式输出
soup.header.div.descendants #列出子子孙孙的节点
.parent #列出父节点

搜索文档树

就是前面用的find\find_all

CSS选择器

它既可以作为遍历树也可以作搜索。

soup.select(“header h1”)

也可以通过某个tag下的直接子标签遍历

soup.select(“div>a”) #即div下所有的a标签

当搜索用时

soup.select(‘a[href^=“http://www.santostang.com/”]’)#搜索以http://www.santostang.com/开始的

使用lxml解析网页

需要安装lxml库

import requests
from lxml import etree
link="http://www.santostang.com//"
headers={'User-Agent':'Mozilla/5.0(Windows;U;Windows NT6.1;en-US;rv:1.9.1.6) Gecko/20091201 Firefox/3.5.7'}
r=requests.get(link,headers=headers)
html=etree.HTML(r.text)
title_list=html.xpath('//h1[@class="post-title"]/a/text()')
print(title_list)

"//h1"代表选取所有

子元素,后面加上class选取class=post-title的元素,/a表示选取h1子元素的a元素,/text() 表示提取a元素中的所有文本。

XPATH的查找方法,用Chrome检查,在要提取的数据那右键复制xPath.

数据保存

  • 存在文件当中,txt和csv
    在这里插入图片描述
with open(r'<文件地址>',"a+") as f:
	f.write(<保存的内容>)
	f.close()
import csv
with open('test.csv','r',encoding='UTF-8') as csvfile:
	csv_reader=csv.reader(csvfile)
import csv
output_list=["1","2"]
with open('test2.csv','a+',encoding="UTF-8",newline='') as csvfile:
	w=csv.writer(csvfile)
	w.writerow(output_list)
  • 存在数据库当中,MySQL和MongoDB
    数据库的指令可以参考我的另一篇文章。
    这里只介绍与本节有关的内容:
    直接给出代码:
import pymysql
#打开数据库连接
db=pymysql.connect("localhost","root","password","数据库名称")
cursor=db.cursor()
#sql插入
sql="""INSERT INT ..........
"""
try:
#sql语句执行
cursor.execute(sql)
#提交到数据库执行
db.commit()
#如果发生错误就回滚
except:
	db.rollback()
db.close

关于MongoDB的内容以后需要使用再进行补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值