php抓取网页匹配url(三个流程获取网页的基础及获取方法(二十五))
优采云 发布时间: 2022-02-24 08:27php抓取网页匹配url(三个流程获取网页的基础及获取方法(二十五))
获取网页的三个过程
获取网页的基础知识: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)
学习使用浏览器菜单栏中的inspect菜单查看浏览器的html语句
其中,requests.get 表示获取对应的对应内容。只有使用它只能读取网页的一些设置值,比如语言设置、响应状态值等等。
自定义请求
这部分主要是解决一些网页必须设置一些参数才能获取的问题。这部分的内容包括传递URL参数、自定义请求头、发送POST请求、设置超时等。
传递 URL 参数
将获取代码修改为以下带参数的请求
key_dict={
'key1':'value1','key2':'value2'}
r=requests.get('http://httpbin.org/get',params=key_dict)
它形成了我们需要的 URL 格式
自定义请求标头
这部分的内容需要浏览器-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)
暂停
限制访问网页的时间。
只需在请求功能后添加
超时=特定值
爬豆瓣代码
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 中)
一般使用
浏览器审查
先给出完整代码
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 也可以模拟浏览器滑动点击,本文文章 仅供入门。
高级操作(待补充)解析网页正则表达式
正则表达式的内容写在我的另一篇文章文章中,这里主要写如何解析网页。
重新匹配
重新*敏*感*词*
m=re.match('www','', flags=0)
打印(m.span)
打印(m.start)
打印(m.end)
您还可以将第一个参数替换为正则表达式。(匹配时一般采用贪心匹配的形式),匹配后通过group调用。group(0)为原字符串,1为左,1为右,不取任何内容。正则匹配中,一般字符串需要转义转义。
研究
re.match 只能从字符串的开头进行匹配,而 re.search 可以扫描整个字符串并返回第一个成功的匹配项。具体参数设置方法同re.match。
重新查找
它的优点是可以找到所有匹配的结果并显示在一个列表中,而前两个只能找到一个。
re.findall('(.*?)',text),只提取括号内的内容。(后面学习html后也需要补充)
美丽汤
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="特定类")
返回一个列表。
其他功能
美化:soup.prettify()
迭代文档的数量
汤头.h1
soup.header.div.contents #将其子节点输出到列表中
soup.header.div.descendants #列出后代的节点
.parent #列出父节点
搜索文档树
就是前面使用的 find\find_all
CSS 选择器
它既可以用作遍历树,也可以用作搜索。
汤.select(“标题h1”)
也可以遍历一个标签下的直接子标签
soup.select("div>a") #即div下的所有a标签
搜索时
soup.select('a[href^=""]')#搜索开头
使用 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。
数据保存
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)
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的内容,后面需要用到和补充